将右值按值传递给函数时,为啥不调用复制构造函数
Posted
技术标签:
【中文标题】将右值按值传递给函数时,为啥不调用复制构造函数【英文标题】:Why isn't the copy-constructor called when passing rvalue by value to function将右值按值传递给函数时,为什么不调用复制构造函数 【发布时间】:2018-01-20 20:12:48 【问题描述】:这是我不知何故错过的一件事,但我很惊讶。考虑以下代码示例:
#include <iostream>
class A
int a;
public:
A(int a) : a(a) std::cout << "Normal constructor called." << std::endl;
A(const A& orig) : a(orig.a) std::cout << "Copy constructor called." << std::endl;
;
void testFunction1(const A arg) std::cout << "testFunction1()" << std::endl;
void testFunction2(const A& arg) std::cout << "testFunction2()" << std::endl;
int main()
testFunction1(A(2));
testFunction2(A(2));
return 0;
我期望得到以下结果:
/* Normal constructor called. */
/* Copy constructor called. */
/* testFunction1() */
/* Normal constructor called. */
/* testFunction2() */
但我错了。确切的结果如下:
/* Normal constructor called. */
/* testFunction1() */
/* Normal constructor called. */
/* testFunction2() */
当我将A(2)
按值传递给testFunction1()
时,为什么没有调用复制构造函数?这是否意味着在 C++98 中通过值或引用传递右值没有区别?是优化吗? A(2)
和 arg
完全一样 testFunction1()
中的对象吗?
【问题讨论】:
可能是copy elision。 @Someprogrammerdude - 谢谢,我会检查的。以前从未听说过。 如果您从未听说过,那么您可能会阅读一些不错的 C++ 书籍...强烈推荐 Meyers 和 Sutter 书籍。跨度> 【参考方案1】:是优化吗?
是的!它被称为 Copy Elision,如果可能,根据编译器,可以省略(绕过)副本。
因此,在您的情况下,编译器知道它可以在不调用复制构造函数的情况下逃脱,并且正是这样做的。请注意,即使您使用了arg
,例如调用A
的打印成员函数,编译器仍然可以使用复制省略来进行优化。换句话说,不使用arg
并不是造成这种行为的原因。
如果您使用古老的编译器,或调整当前编译器的设置,您可能会首先看到预期的结果。
使用c++17,在这种情况下可以保证复制省略,正如 Guillaume Racicot 提到的那样。
【讨论】:
我什至要提一下,在他的情况下,在 C++17 中可以保证复制省略以上是关于将右值按值传递给函数时,为啥不调用复制构造函数的主要内容,如果未能解决你的问题,请参考以下文章