[英]Why isn't rvalue copy constructor used for assignment from temporary?
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class test {
public:
test(int y) {
printf(" test(int y)\n");
}
test() {
printf(" test()\n");
}
test(test&&c) noexcept {
printf(" test(test&&c) noexcept\n");
}
test(const test&z) {
printf(" test(const test&z)\n");
}
test& operator=( test&&e) {
printf(" test& operator=( test&&e)\n");
return *this;
}
};
int main()
{
test o ;
o = 4;
return 0;
}
The Output :
" test() "
" test(int y) "
" test& operator=( test&&e ) "
I thought that this line in the code o = 4 is creating an rvalue of object of the class ( test ) and passing it to the overloaded operator ( operator = )我认为代码 o = 4 中的这一行正在创建 class(测试)的右值 object 并将其传递给重载运算符(operator =)
But when i changed但是当我改变
test& operator=( test&&e )
into进入
test& operator=( test e )
and run the code again:并再次运行代码:
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class test {
public:
test(int y) {
printf(" test(int y)\n");
}
test() {
printf(" test()\n");
}
test(test&& c) noexcept {
printf(" test(test&&c) noexcept\n");
}
test(const test& z) {
printf(" test(const test&z)\n");
}
test& operator=(test e) {
printf(" test& operator=( test e)\n");
return *this;
}
};
int main()
{
test o;
o = 4;
return 0;
}
The Output :
" test() "
" test(int y) "
" test& operator=( test e ) "
While I expected this Output after the change:虽然我预计更改后会出现此 Output:
" test() "
" test(int y) "
" test(test&&c) noexcept "
" test& operator=( test e ) "
Because when i changed因为当我改变
test& operator=( test&&e )
into进入
test& operator=( test e )
the overloaded operator ( operator = ) now takes an object of the class test as parameter ( pass by value ) and the value that is passed to it is an rvalue so I expected that the constructor test(test&&c) noexcept
will be called重载运算符 ( operator = ) 现在将 class 测试的 object 作为参数(按值传递),传递给它的值是一个右值,所以我预计构造函数test(test&&c) noexcept
将被调用
So why the constructor那么为什么构造函数
test(test&&c) noexcept
is not called?是不是叫?
Explanation why I have this expectation:解释为什么我有这种期望:
because when you write this code and run it:因为当你编写并运行这段代码时:
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class test {
public:
test(int y) {
printf(" test(int y)\n");
}
test() {
printf(" test()\n");
}
test(test&& c) noexcept {
printf(" test(test&&c) noexcept\n");
}
test(const test& z) {
printf(" test(const test&z)\n");
}
test& operator=(test e) {
printf(" test& operator=( test e)\n");
return *this;
}
};
int main()
{
test o;
test x;
o = move(x); // this function ( move () ) returns an rvalue of its argument
return 0;
}
The Output :
" test() "
" test() "
" test(test&&c) noexcept "
" test& operator=( test e ) "
edit: this code编辑:这段代码
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class test {
public:
test(int y) {
printf(" test(int y)\n");
}
test() {
printf(" test()\n");
}
test(test&& c) noexcept {
printf(" test(test&&c) noexcept\n");
}
test(const test& z) {
printf(" test(const test&z)\n");
}
test& operator=(test e) {
printf(" test& operator=( test e)\n");
return *this;
}
};
int main()
{
test o;
test x;
o = x;
return 0;
}
The Output :
" test() "
" test() "
" test(const test&z) "
" test& operator=( test e ) "
So why the constructor
test(test&&c) noexcept
is not called?那么为什么不调用构造函数test(test&&c) noexcept
呢?
This is due tonon-mandatory copy elison prior to C++17.Under certain circumstances, the compilers are permitted , but not required to omit the copy and move (since C++11) construction of class objects .这是由于 C++17 之前的非强制复制 elison。在某些情况下,允许编译器,但不要求省略 class 对象的复制和移动(C++11 起)构造。
You can verify this by providing the flag -fno-elide-constructors
in your 2nd example.您可以通过在第二个示例中提供标志-fno-elide-constructors
来验证这一点。 And you'll get your expected output. Demo .您将获得预期的output.Demo 。
class test {
public:
test(int y) {
printf(" test(int y)\n");
}
test() {
printf(" test()\n");
}
test(test&& c) noexcept {
printf(" test(test&&c) noexcept\n");
}
test(const test& z) {
printf(" test(const test&z)\n");
}
test& operator=(test e) {
printf(" test& operator=( test e)\n");
return *this;
}
};
int main()
{
test o;
o = 4;
return 0;
}
Output with -fno-elide-constructors
flag: Output带有-fno-elide-constructors
标志:
test()
test(int y)
test(test&&c) noexcept
test& operator=( test e)
And if you don't provide this flag, then compilers are allowed to elide the copy/move construction in this situation and hence you were getting the output you mentioned.如果您不提供此标志,则允许编译器在这种情况下省略复制/移动构造,因此您将获得您提到的 output。
Note that from C++17 onwards, the flag -fno-elide-constructors
won't have any effect on the output becasue of the mandatory copy elison .请注意,从 C++17 开始,由于强制复制 elison ,标志-fno-elide-constructors
不会对 output 产生任何影响。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.