gpt4 book ai didi

c++ - 为什么返回时调用的是拷贝构造函数而不是 move 构造函数?

转载 作者:可可西里 更新时间:2023-11-01 16:26:44 25 4
gpt4 key购买 nike

假设我有类(class) MyClass具有正确的 move 构造函数并且其复制构造函数被删除。现在我像这样返回这个类:

MyClass func()
{
return MyClass();
}

在这种情况下, move 构造函数在返回类对象时被调用,一切都按预期进行。

现在假设MyClass有一个 << 的实现运算符(operator):

MyClass& operator<<(MyClass& target, const int& source)
{
target.add(source);
return target;
}

当我更改上面的代码时:

MyClass func()
{
return MyClass() << 5;
}

我收到编译器错误,复制构造函数无法访问,因为它已被删除。但为什么在这种情况下完全使用复制构造函数?

最佳答案

Now I am returning this class via lvalue like this:

MyClass func()
{
return MyClass();
}

不,返回的表达式是一个xvalue(一种右值),用于初始化按值返回的结果(自 C++17 以来事情有点复杂,但是这仍然是它的要点;此外,您使用的是 C++11)。

In this case the move constructor gets called when returning the class object and everything works as expected.

的确;一个右值将初始化一个右值引用,因此整个事情可以匹配 move 构造函数。

When I change the code above:

…现在表达式是MyClass() << 5 ,其类型为 MyClass& .这绝不是右值。这是一个左值。它是一个引用现有对象的表达式。

所以,没有明确的 std::move ,这将用于复制初始化结果。而且,由于您的复制构造函数已被删除,因此无法正常工作。


令我惊讶的是该示例完全可以编译,因为临时变量不能用于初始化左值引用(您的运算符的第一个参数),尽管已知某些工具链 (MSVS) 接受它作为扩展。


then would return std::move(MyClass() << 5); work?

是的,我相信是这样。

然而,这看起来很奇怪,让读者仔细检查以确保没有悬空引用。这表明有更好的方法可以实现此目的,从而生成更清晰的代码:

MyClass func()
{
MyClass m;
m << 5;
return m;
}

现在您仍然可以 move (因为 that's a special rule when return ing local variables )而没有任何奇怪的滑稽 Action 。而且,作为奖励,<<调用完全符合标准。

关于c++ - 为什么返回时调用的是拷贝构造函数而不是 move 构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56751481/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com