提问人:bugcreator 提问时间:1/2/2022 最后编辑:cigienbugcreator 更新时间:1/2/2022 访问量:96
在 c++ 中,复制初始化使用什么特殊成员函数?
What special member function is used for copy initialization in c++?
问:
我正在测试 c++ 类初始化。
class Point
{
private:
int x,y;
public:
Point() = delete;
Point(int a):x(a), y(0) { std::cout << "Conversion" << std::endl;}
Point(const Point&) { std::cout << "Copy constructor" << std::endl;}
//Point(const Point&) = delete;
Point& operator=(const Point&) = delete;
Point(Point&&) = delete;
Point& operator=(Point&&) = delete;
};
int main()
{
Point p1(5); //case1
Point p2 = 5; //case2
return 0;
}
在上面的代码中,我认为“5”首先会通过转换构造函数转换为两个 case1/2 的临时对象。然后,我希望复制构造函数必须用于初始化 p1 和 p2。但是,事实并非如此。 当我运行此代码时,我在控制台中只看到两条“转换”消息。没有“复制构造函数”消息。
尽管我删除了所有复制构造函数、移动构造函数、复制赋值运算符和移动赋值运算符,但这段代码运行良好。
如果您让我知道在为“5”创建临时对象后将使用什么特殊成员函数进行初始化,我将不胜感激,
我正在使用带有 std=c++17 选项的 g++ 编译器。
答:
4赞
user12002570
1/2/2022
#1
案例一
在案例 1 中,使用了转换构造函数,因为您提供了一个可以将 转换为 的构造函数。这就是为什么这个构造函数被称为转换构造函数的原因。int
Point
案例二
在以下情况下,编译器需要省略类对象的复制和移动构造,即使复制/移动构造函数和析构函数具有可观察到的副作用。这些对象被直接构造到存储中,否则它们将被复制/移动到其中。复制/移动构造函数不需要存在或可访问:
在对象的初始化中,当初始值设定项表达式是与变量类型相同的类类型(忽略 cv-qualification)的 prvalue 时。
在情况 2 中,即使您复制/移动构造函数,也只会使用转换构造函数。这是由于上面引用的强制性复制elison(在C++17中)。delete
评论
0赞
Nathan Pierson
1/2/2022
根据 cppreference 在复制初始化的情况下,即使发生省略,也需要适当的构造函数可访问。这似乎与观察到的行为不匹配,在该行为中,删除复制和移动构造函数仍允许进行省略。编辑:哎呀,我没有意识到该段落具有“(直到 C++17)”标签并反映了预先强制的省略规则。
0赞
bugcreator
1/2/2022
@Anoop Rana:谢谢你的回答。在我看来,这个复制省略看起来与 RVO 非常相似。我认为这个强制性的复制省略可以从 C++17 获得,所以我在 c++14 中测试了相同的代码。当我使用 std=c++14 选项编译此代码时,最后我通过删除 Point(Point &&) 的函数得到了一个错误。但是有一件非常奇怪的事情。我已将移动构造函数定义为 ,并且编译完成。但是当我运行代码时,我仍然能够看到 2 条“转化”消息。Point(Point&&) { std::cout << "Move constructor" << std::endl;}
0赞
user12002570
1/2/2022
@bugcreator 您仍然会看到 2 个“转换”,因为 C++17 之前的编译器被允许直接构建到存储中。请注意我上一句话中的单词。这并不意味着他们必须这样做。因此,实际上大多数编译器(在 C++17 之前)都曾经逃避复制/移动构造,因为它们被允许这样做。另一方面,在 C++17 中,它们需要 .allowed to
0赞
bugcreator
1/2/2022
我以为皮尔森提到的@Nathan就是这种情况。虽然,Move Constructor 被省略了,但它必须在 c++14 中可访问。
评论
x
y