考虑给定的代码
struct ABC
{
ABC()
{
std::cout<<" Calling from default constructor";
}
ABC(const ABC ©)
{
std::cout<<"Calling from copy constructor";
}
};
int main()
{
ABC abc = ABC();
}
我有两个问题
Q1)从复制构造函数参数声明中删除const会产生错误。为什么呢?
Q2)添加const关键字后,我没有看到对复制构造函数的调用。为什么?复制构造函数没有被调用,为什么const是必要的?
TIA
答案 0 :(得分:5)
你需要const,因为你试图用一个临时的ABC()来初始化abc。因此,如果构造函数不是const,则编译器必须拒绝代码。
使它成为const之后,代码就是标准投诉,编译器可以编译它。但是,如本标准所述,允许在这种情况下优化副本,因此它会删除对复制构造函数的调用。
答案 1 :(得分:3)
Q1)从副本中删除const 构造函数参数声明 给出错误。为什么呢?
ABC abc = ABC();
相当于
ABC abc((ABC()));
由于您将临时文件传递给复制构造函数,因此它只能绑定到const引用,而不是非const引用。
复制构造函数可以使用非const引用(例如std::auto_ptr
),但这意味着它们的使用受到更多限制。
Q2)添加const关键字I后 没有看到对副本的调用 构造函数。为什么?复制构造函数 没有被叫,所以为什么 const必要吗?
在给定的场景中,允许编译器优化对构造函数的冗余调用。为什么只创建一个默认对象来复制它,如果它只能单独调用默认构造函数?
但是,即使对复制构造函数的调用进行了优化,编译器也必须检查代码是否有效 - 就像复制构造没有被优化一样。
答案 2 :(得分:2)
const是必要的,因为不允许将临时绑定到非const引用。即使编译器优化了复制构造函数,也不会直到后一阶段。
C ++ 0x标准通过添加rvalue引用来解决这个问题。这将允许您将const参数删除到非const ...
ABC( ABC&& copy)
虽然你仍然想要常规的参考拷贝构造函数......
答案 3 :(得分:1)
如果你还定义了赋值运算符,你会发现甚至没有调用它:编译器在ABC abc = ABC();
中优化ABC abc;
,因为它们具有相同的语义。 / p>
关于另一个疑问,G ++并没有抱怨将复制构造函数参数声明为非const(甚至不是-Wall -W -std=c++98
)。无论如何都没有检查出这个标准。