带大括号初始化列表的赋值是否会引发临时对象的冗余移动?
代码行为分析
先看给出的两段代码:
第一段是生成字符串的函数:
std::string generateResponse() { std::string response {"Some generated response"}; return response; }
第二段是调用函数并处理结果的代码:
std::string response {}; try { response = {generateResponse()}; } catch (const std::exception& e) { // Some error handling and logging throw; } // Do something else here... // ... and finally return the value return response;
针对你的两个疑问,具体分析如下:
关于疑问1:
从语法逻辑上看,response = {generateResponse()}会先通过移动构造函数,用generateResponse()返回的右值构造一个临时std::string对象,再调用移动赋值运算符把这个临时对象赋值给response——也就是理论上会发生两次移动操作。
但在C17及之后的标准中,编译器会强制执行复制消除,直接省略这个临时对象的构造过程,实际效果等同于直接移动赋值;C17之前的编译器也几乎都会做这个优化,所以实际运行时大概率只会有一次移动操作。而且std::string的移动本身只是转移内部指针,开销极低,就算没优化也几乎不会影响性能。关于疑问2:
如果写成response = generateResponse(),则是直接调用std::string的移动赋值运算符,把generateResponse()返回的右值直接赋值给response,只会发生一次移动操作,这是更直接的写法。
内容的提问来源于stack exchange,提问作者Torsten Römer
相关产品推荐
相关产品推荐

