关于 C++ 的误解和都市传说
注意:本节需要更多内容
本节包含初步信息,但需要更多常见问题。如果您能提供一个关于 C++ 的常见误解或误区,请将鼠标悬停在任何 FAQ 标题上,然后点击“推荐改进”图标。(如果您还能提供对该误解的简要解答,那就太好了,但这不是强制性的。)
为什么 C++ 没有现代编译器和工具来支持重构之类的功能?为什么我必须实现一个完整的 C++ 编译器来解析 C++,而不是像其他语言那样可以插入现有实现?
它有,而且你不需要。使用 Clang——一个开源的、世界级的 C++ 编译器,它从头开始设计,旨在模块化、可插拔、可扩展和可重用,让你可以构建各种 C++ 工具,而无需首先编写 C++ 编译器。许多项目都在使用它,并且每天都有更多的项目采用它。
在 Clang 之前,唯一的开源 C++ 编译器是 GCC/g++,它在设计上出于哲学和技术原因是一个封闭且不可重用的实现。这种缺乏可重用性是 Clang 作为替代和独立开发的开源 C++ 编译器被创建的主要原因。现在 Clang 炙手可热,GCC 也开始效仿,其 C++ 编译器正在被重新设计和开放,成为一个有竞争力且可重用的 C++ 实现,其他人也可以在其基础上进行构建。竞争是件好事!
过去,编写 C++ 工具更困难,因为没有开源的可重用 C++ 解析器。现在有了。尽情发挥吧!
为什么 C++ 会到处创建无用的对象深拷贝,比如按值返回?
C++ 是一种值语义语言,默认情况下,它会复制指定为参数或返回的值。程序员可以通过使用引用语义来避免复制,或者编译器可以通过使用复制消除来避免复制。
现代 C++(C++11 及更高版本)通过支持移动语义直接消除了许多临时对象,这允许将一个对象的内部结构直接转移到另一个对象,而无需实际执行深拷贝。更好的是,在常见情况下,例如按值传递和按值返回,移动语义会自动开启,代码无需做任何特殊处理。这为您提供了使用值类型的便利和代码清晰度,以及引用类型的性能。
C++ 代码一直都很快,但现在,如果您使用支持移动语义的新编译器编译现有的 C++11 之前的代码,您可能会发现您的旧代码运行得更快,因为编译器能够对返回值和其他临时对象进行轻量级移动而不是深拷贝。这也不依赖于智能的编译器优化——语言现在保证会发生移动。
什么是复制消除?什么是 RVO?
复制消除是一种编译器技术,可用于即将被销毁的对象需要复制的情况。编译器需要在对象作为参数传递给函数或作为函数返回值时进行复制。
在即将被复制的对象即将被销毁的情况下,例如当函数的参数是一个临时对象,或者当返回的对象是局部于被调用函数时,编译器可以通过用原始对象替换而不是销毁它来消除复制。
复制消除的一个例子是返回值优化(RVO),它可以在函数中的每个返回语句都返回一个特定的局部变量时使用。
由于复制构造函数和析构函数可能具有副作用,因此符合标准的程序有可能检测到复制消除正在发生。编译器转换如果可以被符合标准的程序检测到,则不受“as if”规则的约束,因此这些优化除非 C++ 标准明确允许复制消除,否则是不合法的。