R_K*_*app 8 c++ copy-constructor assignment-operator language-lawyer c++11
请考虑以下代码:
#include <memory>
#include <vector>
class A
{
private:
std::vector<std::unique_ptr<int>> _vals;
};
int main()
{
A a;
//A a2(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译器A没有问题地编译它,除非我取消注释A a2(a);它抱怨复制构造函数std::unique_ptr被删除的那一行,因此我不能复制构造A.然而,即使我将该行留下注释,编译器B也会提出投诉.也就是说,当我实际尝试使用它时,编译器A只生成一个隐式定义的复制构造函数,而编译器B则无条件地这样做.哪一个是正确的?请注意,如果我使用std::unique_ptr<int> _vals;而不是std::vector<std::unique_ptr<int>> _vals;两个编译器正确地隐式删除复制构造函数和赋值运算符(std::unique_ptr具有显式删除的复制构造函数,而std::vector不是).
(注:获取代码编译器B到编译是很容易的 - 只要明确地删除拷贝构造函数和赋值运算符,并且它能够正常工作这不是问题的问题,它是要了解正确的行为.)
即默认而不是定义为已删除的复制/移动构造函数被隐含定义当ODR使用([basic.def.odr]),当需要用于恒定评价([expr.const]),或者当它在第一次声明后明确默认.
A复制构造函数是默认的,所以只有在使用它时才会隐式定义它.A a2(a);只是这样一种使用 - 所以这个声明会触发它的定义,这会使程序形成错误.在使用复制构造函数之前,不应该定义它.
编译器B拒绝该程序是错误的.