当返回作为const引用的字符串时,编译器是否避免复制?
Does the compiler avoid a copy when returning a string that is taken as const reference?
我想知道编译器是否会在以下情况下优化副本。我有一个类,它唯一的资源成员是一个可能有几KB大的字符串。我想让这个类的一个公共成员访问那个字符串,我不确定我应该让这个成员返回一个引用还是简单地按值返回。假设我选择按值返回
class A {
public:
A();
~A();
std::string getString() { return str; }
private:
std::string str;
}
int main() {
A *a = new A;
const std::string& str = a->getString();
std::cout << str;
}
如果我把结果作为const std::string&
作为main
,编译器会优化和避免复制吗?
在这种情况下,编译器将优化掉一个副本的可能性很小,但可能性很小。
注意,如果副本被优化了,调用者的临时本质上被绑定为对对象的类成员的const
引用。const
表示参考值不可改变。
对于这个问题中所示的代码,编译器可以向自己证明,当const
引用仍然在作用域内时,没有任何可能改变类成员的内容,因此进行此优化是安全的。
但在更普遍的情况下,事情很快就会变得混乱。如果有其他类方法可能改变被引用的类成员的内容,如果在const
引用的生命周期内调用了定义不可见的函数或方法;最可能的结果是,编译器将无法知道是否有可能在const
引用的整个执行范围内修改被引用的类成员,因此它将被迫复制字符串,以保证其const
性。
编译器可以自由地只进行那些在格式良好的程序中不会导致可见的、可观察到的变化的优化。如果编译器不能证明优化结果没有可见的、可观察到的变化,那么优化将不会执行。
注:注意,"修改"也包括销毁。建议的优化将const
引用绑定到动态范围内的对象。如果有任何对delete
的中间调用——显式或隐式地作为调用各种库容器方法的一部分——编译器还必须向自己证明 delete
d对象不能是绑定const
引用的对象。
相关文章:
- C/C++预处理器是否可以检测一些编译器选项
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- __CHAR_BIT__宏是否为 MSVC 编译器预定义?
- 如何检测VS C++编译器是否支持C++11?
- 编译器是否必须始终删除 try-catch 块(如果它被证明是非抛出的)
- 是否允许编译器省略对指针的 &* 运算符的组合调用?
- 编译器是否强制根据模板参数计算表达式?
- Visual Studio 中是否有来自代码块的编译器标志的类似物?
- C++编译器是否优化了顺序静态变量读取?
- c++ 编译器是否保护常量内存地址免受任何更改?
- 不同版本的编译器(例如GCC)是否会产生不同的性能?
- G++ 编译器是否在未使用返回值的情况下将 constexpr 函数视为常规函数?
- 编译器是否对 std::frexp 进行了内联调用?
- 是否可以将不同的编译器嵌入到我的应用程序中?
- GCC 编译器是否应该对涉及 [[fallthrough]] 属性的格式错误的C++代码进行诊断?
- 当作为参数传入时,是否可以由编译器指定模板类参数?
- 是否有任何 2 补充平台/编译器,其中有符号移位不做通常的事情?
- 编译器是否会创建vtable,而不考虑在c++中创建对象
- 是否允许编译器优化掉局部易失性变量