在 C++11 中,RVO 需要移动 constructor/assignment 吗?
Is a move constructor/assignment needed for RVO to kick in in C++11?
例如:
在已接受的答案中 ,
Does copy elision and RVO would still work for classes without move
constructors?
Yes, RVO still kicks in. Actually, the compiler is expected to pick:
RVO (if possible)
在接受的答案中 ,
Under non-guaranteed copy elision rules, this will create a temporary,
then move from that temporary into the function's return value. That
move operation may be elided, but T must still have an accessible move
constructor even if it is never used.
关键是我认为 RVO 和“左值移动”(或如何称呼它们)是 2 个完全独立的操作,但我的同事告诉我,要启动 RVO,class 返回需要一个移动构造函数。所以我检查了互联网和 SO 显然,无法快速找到信息...
简答:没有。
RVO 在 C++11 之前也存在,当时还没有 "move constructor" 这样的东西。在这种情况下,复制构造函数是唯一的要求。
您引用的 "Under non-guaranteed copy elision rules..." 段落指的是 pre-C++17 世界,其中 "mandatory copy elision" 还不是语言的一部分.
自 C++17 起,编译以下代码(保证零 copies/moves):
struct foo
{
foo() = default;
foo(const foo&) = delete;
foo(foo&&) = delete;
};
foo get_foo() { return foo{}; }
int main()
{
foo f{get_foo()};
}
否,如果复制构造函数可用。
在 C++17 之前并保证 copy-elision、 移动构造函数或复制构造函数必须可用以使代码合法。 Elision 只是一种优化,并不影响代码是否可以编译。
即有two-steps个过程:
- 评估语句
return <expr>;
是否合法,在 C++17 之前要求(禁止转换)存在复制构造函数,或者在存在临时构造函数的情况下存在移动构造函数 和访问。
- 如果可能,应用 Return 值优化并省略对所述构造函数的调用。
考虑到这一点,让我们回顾一下引文:
Does copy elision and RVO would still work for classes without move constructors?
是的,RVO 仍然有效。实际上,编译器应该选择:RVO(如果可能)
Yes 应该在合法代码的上下文中理解。如果代码无法编译,那么这个问题就没有意义了。
Under non-guaranteed copy elision rules, this will create a temporary, then move from that temporary into the function's return value. That move operation may be elided, but T must still have an accessible move constructor even if it is never used.
这是一个short-cut;试图在考虑到可能缺少移动构造函数的情况下制定句子,因此回退到复制构造函数只会混淆解释,而且 OP 没有表示正在考虑这种情况。
例如:
在已接受的答案中 ,
Does copy elision and RVO would still work for classes without move constructors?
Yes, RVO still kicks in. Actually, the compiler is expected to pick: RVO (if possible)
在接受的答案中
Under non-guaranteed copy elision rules, this will create a temporary, then move from that temporary into the function's return value. That move operation may be elided, but T must still have an accessible move constructor even if it is never used.
关键是我认为 RVO 和“左值移动”(或如何称呼它们)是 2 个完全独立的操作,但我的同事告诉我,要启动 RVO,class 返回需要一个移动构造函数。所以我检查了互联网和 SO 显然,无法快速找到信息...
简答:没有。
RVO 在 C++11 之前也存在,当时还没有 "move constructor" 这样的东西。在这种情况下,复制构造函数是唯一的要求。
您引用的 "Under non-guaranteed copy elision rules..." 段落指的是 pre-C++17 世界,其中 "mandatory copy elision" 还不是语言的一部分.
自 C++17 起,编译以下代码(保证零 copies/moves):
struct foo
{
foo() = default;
foo(const foo&) = delete;
foo(foo&&) = delete;
};
foo get_foo() { return foo{}; }
int main()
{
foo f{get_foo()};
}
否,如果复制构造函数可用。
在 C++17 之前并保证 copy-elision、 移动构造函数或复制构造函数必须可用以使代码合法。 Elision 只是一种优化,并不影响代码是否可以编译。
即有two-steps个过程:
- 评估语句
return <expr>;
是否合法,在 C++17 之前要求(禁止转换)存在复制构造函数,或者在存在临时构造函数的情况下存在移动构造函数 和访问。 - 如果可能,应用 Return 值优化并省略对所述构造函数的调用。
考虑到这一点,让我们回顾一下引文:
Does copy elision and RVO would still work for classes without move constructors?
是的,RVO 仍然有效。实际上,编译器应该选择:RVO(如果可能)
Yes 应该在合法代码的上下文中理解。如果代码无法编译,那么这个问题就没有意义了。
Under non-guaranteed copy elision rules, this will create a temporary, then move from that temporary into the function's return value. That move operation may be elided, but T must still have an accessible move constructor even if it is never used.
这是一个short-cut;试图在考虑到可能缺少移动构造函数的情况下制定句子,因此回退到复制构造函数只会混淆解释,而且 OP 没有表示正在考虑这种情况。