复制构造函数/复制赋值和正常函数调用优化在编译时有什么区别吗?

时间:2016-06-21 12:10:35

标签: c++ compilation

在测试一个小例子时遇到了一个有趣的编译错误:

#include <iostream>

using namespace std;

class A
{
public:
   A() { cout <<"A created." <<endl; }
   A(A& a) { cout <<"A created by copy constructor." <<endl; }
   ~A() { cout <<"A destoryed." <<endl; }
};

A CreateObject()
{
    A obj;
    return obj;
}   

int main()
{
    A a;
    A b;

    b= CreateObject();

    return 0;
}

它很简单,可能根本没有任何问题。但是,它在编译时提示:

copy_constructor.cpp: In function ‘int main()’:
copy_constructor.cpp:23: error: no matching function for call to ‘A::A(A)’
copy_constructor.cpp:9: note: candidates are: A::A(A&)

似乎程序在编译“b = CreateObject();”时试图调用复制构造函数但是没有匹配的拷贝构造函数。这不应该发生,因为它只是一个赋值语句,编译优化中构造函数和普通函数之间有什么区别吗?

2 个答案:

答案 0 :(得分:2)

A(A& a) { cout <<"A created by copy constructor." <<endl; }
...
b = CreateObject();

根据C ++ 03标准,这是无效的。

在C ++ 03中,b = CreateObject()实际上可能会扩展为b = A(CreateObject());。这只是&#34;固定&#34;在C ++的更高版本中,现在禁止创建临时副本。

CreateObject()返回一个r-hand值,该值只能由具有A(const A& a)签名的复制构造函数使用。如果没有const修饰符,它只适用于l-hand值。

E.g。 b = a对于该签名和扩展仍然有效,因为您可以在构造函数中修改a

这仍然是可复制的设置clang ++到C ++ 98标准:http://coliru.stacked-crooked.com/a/50c25c469420ab0f

较早版本的Visual-C ++显示OP显示的精确错误。

g ++无法正确验证这一点,即使在明确指定C ++ 98时也是如此。

另见https://stackoverflow.com/a/13898867/2879325

答案 1 :(得分:0)

您发布的代码编译得很好。但是,您应该将复制构造函数从A(A&)更改为A(const A&)