本人为大三本科生,因为对游戏引擎感兴趣自己正在学习并且尝试实践 c++。这是我的项目链接LRE2。最近看了很多文章,觉得自己对 cpp 理解很有问题,比如说关于share_ptr
的滥用问题,在个人的项目中处理的非常差。还有就是关于语言的高级特性也是完全不明白,因此希望得到一些关于 cpp 学习的路径。很多推荐的材料感觉都偏基础,而且大部分都是视频材料,个人吸收效果不是很好。如果可以的话希望得到一些文字材料推荐。
1
111qqz 2023-03-29 10:04:18 +08:00
|
3
LaTero 2023-03-29 10:26:04 +08:00 via Android
core guidelines 看一下?都很实用的。https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
|
4
inhzus 2023-03-29 10:39:54 +08:00
有看过经典三件套吗 Effective C++, More Effective C++, Effective Modern C++
高级特性比如 C++ 20/23 ,cppcon 有一些大纲性质的视频分类的挺好,大概了解之后,自己用一用就会了。 其余的参考 cppreference 比如 C++17 core language features ,逐个查漏补缺... |
5
sl0000 2023-03-29 10:46:14 +08:00 1
高速上手 C++ 11/14/17/20 https://changkun.de/modern-cpp/
|
6
zeal7s 2023-03-29 10:50:16 +08:00
shared_ptr 主要是跟所有权相关,一般一个类用拥有一个对象才会使用 shared_ptr ,如果只是 access 一个对象,用 weak_ptr 或者 raw pointer 就可以。
举个例子,父窗口在逻辑上拥有子窗口,那么父窗口类中就用 shared_ptr hold 住子窗口对象。当子窗口需要使用的父窗口的一些函数时,子窗口就通过 weak_ptr 来 access 父窗口对象进而调用父窗口的函数。这样可以避免循环引用。 一般 shared_ptr 和 weak_ptr 配对使用,unique_ptr 和 raw pointer 配对使用,你分别用这两种方法来实现一个双向链表的功能比如插入和删除就能有所体会。 平时写代码能用 unique_ptr/raw_pointer 配对就尽量用,避免 shared_ptr 引用计数的开销。但是有些情况 shared_ptr 仍然不得不用:比如实现 Graph 相关的算法时候,一个节点会被两个以上节点指向,而且也没有明确的所有权概念。 另外,仅在需要操作对象生命周期时使用智能指针作为函数参数,这部分可以看 C++ Core Guidlines ,讲得比较细。 我自己也是感觉很多 C++书籍讲解智能指针的使用时挺模糊的,比如 C++ primer ,看完语法是会了,但是一写代码就感觉不对劲,每次都会自我怀疑这样写到底对不对。 平时学 C++我比较常看 CppCon 演讲,可以学到很多。 B 站推荐两个 Up 主,感觉 C++相关的系列视频讲得挺好的: https://space.bilibili.com/1292761396 https://space.bilibili.com/263032155 |
7
yangzhezjgs 2023-03-29 10:51:59 +08:00
我大概理解你的意思,你应该想更多“why”这个层面为什么 C++这么设计和具体场景下该怎么写 C++的建议,推荐几本我最近在看的书:
1.《现代 C++语言核心特性解析》 https://book.douban.com/subject/35602582/ 2.《深入应用 C++11 》 https://book.douban.com/subject/26419368/ 3.《 C++ Software Design 》 https://book.douban.com/subject/35913533/ |
8
zeal7s 2023-03-29 10:59:02 +08:00
我记得 CppCon 里有好几个演讲专门讲智能指针的使用,很细,也有不少坑,你可以去搜搜
|
9
yangzhezjgs 2023-03-29 10:59:34 +08:00
4.《 C++沉思录》也不错,也是研究设计和编程思想,只是成书年代比较早了,也推荐一下
我觉得核心是要通过学习,在脑子里形成一套写代码时的决策树,了解各种写法背后的权衡和优劣,做出相对正确的选择 |
10
chatWell1 2023-03-29 11:12:19 +08:00
1. 《 C++语言的设计与演化》
2. 《深度探究 C++对象模型》 3. 《 STL 深入浅出》 4. 《 C++沉思录》 |
11
Yeen 2023-03-29 11:15:06 +08:00
C++ PRIMER
Inside the c++ object model 深入理解计算机系统 剩下的就是自己实践几个超过 2 万行代码的工程,阅读优秀的开源项目。 good luck |
12
hankai17 2023-03-29 11:49:39 +08:00
9L + 1
书本是对知识的总结 |
13
zuosiruan 2023-03-29 14:14:11 +08:00
游戏引擎感兴趣......进不了米哈游这种级别的厂毫无意义。加油吧 小伙子
|
14
ivvei 2023-03-29 14:25:03 +08:00
shared_ptr 我倾向于直接不用…… 资源谁分配就谁掌控,实在不要了就转走。
|
15
fengjianxinghun 2023-03-29 14:27:36 +08:00 2
|
16
Symbo1ic OP @zeal7s 所有权这块真的很有启发性。在应对你提到的关于 unique 和 raw 搭配的情况,因为感觉 raw 并不是很靠谱,所以总是用 share 暴力解决。所有权这块的设计真的是很难,这块我也是一直没有弄的很明白。这块在这个视频中也会提到吗?另外感谢大家的分享!
|
17
Symbo1ic OP @fengjianxinghun 正巧我有朋友学习过 rust ,说实话我感觉 rust 关于所有权那套解法还有一些思想也许可以套到 cpp 的开发中
|
19
Symbo1ic OP @yangzhezjgs 关于决策这块的说法不能再赞同了!这种东西也许就叫做 cpp 编程技能了吧。能够正确的在不同场景找到最优的解法,这真的很吸引人
|
20
xmmmmovo 2023-03-29 18:38:13 +08:00
游戏引擎......加油......先问一下你之前引擎用的多吗.....
|
22
Symbo1ic OP @xmmmmovo 目前的话有过 unity 游戏开发经验,之前有用 ue 的蓝图试着搭一些小东西。有的时候真的觉得他们在脚本层接口设计十分巧妙
|
23
exch4nge 2023-03-30 10:26:36 +08:00 via iPhone 1
@Symbo1ic
raw 用在能确定指针有效的情况,指针指向对象的生命周期肯定比当前类对象要长,能不用就不用。 其余不用共享的用 unique ,明确表示有所有权。需要所有权转移也用,函数参数返回值等。 (不用转移所有权,但用来延后初始化的场景建议用 optional ) share_ptr 共享用,随处都用的话得避免循环应用,可以用 weak 解决。有时也用 atomic store load 来做原子操作多线程安全切换里面的对象 内存使用大小上,share 最大,有 custom delete 的 unique 稍微大,没有的 unique 跟 raw 一样 性能上 share 最差,unique 与 raw 接近 |
24
zeal7s 2023-03-30 11:14:13 +08:00 1
@Symbo1ic 还是拿父窗口和子窗口来举例子,父窗口生成子窗口并且用 unique_ptr hold 住子窗口,子窗口生成时拿到指向父窗口的 raw pointer 。只要能保证父窗口的生命周期长于子窗口,即父窗口先于子窗口创建,晚于子窗口销毁,就能保证 raw pointer 不失效。
所有权这块的使用原则就是一个对象逻辑上属于谁,所有权就是谁。现代 C++里面有所有权这个概念而其他语言里这个概念比较模糊的原因是,现代 C++通过 RAII 来控制堆上对象的生命周期。一个类拥有一个对象的所有权就表示这个类在调用自己的析构函数时也负责自动调用这个对象的析构函数。所以写程序时,想清楚堆上的对象由谁来负责销毁在逻辑上最合适,那么所有权也就想清楚了。 换一种情况,如果程序中允许父窗口先于子窗口关闭,那么继续让父窗口通过 unique_ptr 持有子窗口就不合适了,因为父窗口销毁时也会自动调用子窗口的析构函数。此时需要一个窗口管理器来拥有所有的窗口,比如在窗口管理器中可以写:std::vector<std::unique_ptr<Window>> allWindows 。这样只要保证窗口管理器类晚于所有窗口销毁就行了。 可以看看 muduo 这个 C++网络库,作者也有出书介绍,网上也有大量的文章和视频介绍。里面有挺多 unique_ptr 和 shared_ptr 用法。 |
25
zeal7s 2023-03-30 11:31:38 +08:00 1
@Symbo1ic 比如你的代码里 https://github.com/hundan2015/LunaticRenderer2/blob/master/lunatic_engine/core/LunaticEngine.h#L14
rendering_core_、entity_manager_和 resource_core_在逻辑上由引擎类负责管理销毁最合适,那么它们使用 unique_ptr 就行了。这里不存在共享所有权的情况,用 shared_ptr 就没必要了。 |
26
DwiwO7a6Uyv33RHs 195 天前
|
27
DwiwO7a6Uyv33RHs 195 天前
可以看下这个网站: https://csguide.cn/cpp
|