移动在 return 上调用的构造函数而不是复制
move constructor called on return instead of copy
今天我发现这段代码不能像我期望的那样工作。
根据我对 L 值的知识,应该调用复制构造函数,而对于 R 值,它应该选择移动构造函数。否则 std::move
的目的是什么,它实际上只转换为 R 值。我原以为 return obj
会调用复制构造函数,但它调用了 move。
我知道复制在这里没有用,但这是关于规则的。如果我的复制构造函数有副作用怎么办,这就是我的情况(我知道它不应该,但从技术上讲它可以 - 例如这里:std::cout 调用)。
标准中是否有任何允许此类行为的内容?还有我怎样才能强制复制?
#include <iostream>
class X
{
public:
X() = default;
X(const X& r): i(r.i)
{
std::cout << "copy ctor" << std::endl;
}
X(const X&& r): i(r.i)
{
std::cout << "move ctor" << std::endl;
}
int i = 0;
};
X foo()
{
X obj;
obj.i = 10;
return obj;
}
int main()
{
X x = foo();
}
move ctor
move ctor
来自 cppreference(强调我的):
If [the returned expression] is an lvalue expression and the conditions for copy elision are met, or would be met, except that [the returned expression] names a function parameter, then overload resolution to select the constructor to use for initialization of the returned value is performed twice: first as if [the returned expression] were an rvalue expression (thus it may select the move constructor or a copy constructor taking reference to const), and if no suitable conversion is available, overload resolution is performed the second time, with lvalue [returned expression] (so it may select the copy constructor taking a reference to non-const).
The above rule applies even if the function return type is different from the type of [the returned expression] (copy elision requires same type)
长话短说,return
会在有意义的时候暗中尝试移动您 return 的内容。它只会作为最后的手段进行复制(例如,没有可用的移动构造函数)。
今天我发现这段代码不能像我期望的那样工作。
根据我对 L 值的知识,应该调用复制构造函数,而对于 R 值,它应该选择移动构造函数。否则 std::move
的目的是什么,它实际上只转换为 R 值。我原以为 return obj
会调用复制构造函数,但它调用了 move。
我知道复制在这里没有用,但这是关于规则的。如果我的复制构造函数有副作用怎么办,这就是我的情况(我知道它不应该,但从技术上讲它可以 - 例如这里:std::cout 调用)。
标准中是否有任何允许此类行为的内容?还有我怎样才能强制复制?
#include <iostream>
class X
{
public:
X() = default;
X(const X& r): i(r.i)
{
std::cout << "copy ctor" << std::endl;
}
X(const X&& r): i(r.i)
{
std::cout << "move ctor" << std::endl;
}
int i = 0;
};
X foo()
{
X obj;
obj.i = 10;
return obj;
}
int main()
{
X x = foo();
}
move ctor
move ctor
来自 cppreference(强调我的):
If [the returned expression] is an lvalue expression and the conditions for copy elision are met, or would be met, except that [the returned expression] names a function parameter, then overload resolution to select the constructor to use for initialization of the returned value is performed twice: first as if [the returned expression] were an rvalue expression (thus it may select the move constructor or a copy constructor taking reference to const), and if no suitable conversion is available, overload resolution is performed the second time, with lvalue [returned expression] (so it may select the copy constructor taking a reference to non-const). The above rule applies even if the function return type is different from the type of [the returned expression] (copy elision requires same type)
长话短说,return
会在有意义的时候暗中尝试移动您 return 的内容。它只会作为最后的手段进行复制(例如,没有可用的移动构造函数)。