简体   繁体   English

为什么右值复制构造函数不用于临时赋值?

[英]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)

Working demo .工作演示


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。


C++17 C++17

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.

相关问题 当按值传递右值到函数时,为什么不调用复制构造函数 - Why isn't the copy-constructor called when passing rvalue by value to function 为什么拷贝构造函数没有在这里消失? - Why isn't the copy constructor elided here? 为什么使用复制构造函数而不是赋值运算符 - Why is the copy constructor being used instead of the assignment operator 为什么在返回临时(rvalue)时在移动构造函数之前调用析构函数 - Why is the destructor called before the move constructor when returning a temporary (rvalue) 尽管传递了一个右值,为什么我的移动构造函数不会被调用? - Despite passing an rvalue, why isn't my move constructor getting called? 为什么在副本分配ctor的末尾没有释放所获取的资源? - Why isn't the acquired resource released at the end of this copy assignment ctor? 为什么调用复制构造函数而不是使用右值初始值设定项的移动构造函数? - Why copy constructor is called instead of move constructor with an rvalue initializer? 是在这里使用复制构造函数,赋值运算符还是两者都使用? - Is the copy constructor, assignment operator, or both used here? 从初始化列表中启动向量时,为什么不使用移动构造(通过隐式构造函数) - Why isn't move construction used when initiating a vector from initializer list (via implicit constructor) 为什么我的链接数据类型复制构造函数不起作用? - Why isn't my linked Data Type Copy Constructor working?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM