首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++11 -我失去了一个移动/复制任务

C++11 -我失去了一个移动/复制任务
EN

Stack Overflow用户
提问于 2013-04-02 18:17:18
回答 2查看 201关注 0票数 4

我在另一个问题中发布了这段代码,但我对它有了新的怀疑:

代码语言:javascript
复制
#include <iostream>
#include <string>
#include <vector>
using namespace std;

class X
{
    public:

    std::vector<double> data;

    // Constructor1
    X():
        data(100000) // lots of data
    {
        cout << "X default constructor called";
    }

    // Constructor2
    X(X const& other): // copy constructor
        data(other.data)   // duplicate all that data
    {
        cout << "X copy constructor called";
    }

    // Constructor3
    X(X&& other):  // move constructor
        data(std::move(other.data)) // move the data: no copies
    {
        cout << "X move constructor called";
    }

    X& operator=(X const& other) // copy-assignment
    {
        cout << "X copy assignment called";
        data=other.data; // copy all the data
        return *this;
    }

    X& operator=(X && other) // move-assignment
    {
        cout << "X move assignment called";
        data=std::move(other.data); // move the data: no copies
        return *this;
    }

};

class X2
{
    public:

    std::vector<double> data;

    // Constructor1
    X2():
        data(100000) // lots of data
    {}

    // Constructor2
    X2(X const& other): // copy constructor
        data(other.data)   // duplicate all that data
    {}

    X2& operator=(X const& other) // copy-assignment
    {
        data=other.data; // copy all the data
        return *this;
    }
};

X make_x()
{
    X myNewObject; // Il normale costruttore viene chiamato qui
    myNewObject.data.push_back(22);
    return myNewObject; // Si crea un oggetto temporaneo prima di ritornare con il move constructor perchè myNewObject dev'essere distrutto
}


int main()
{
    X x1 = make_x(); // x1 has a move constructor


    X2 x2 = make_x(); // x2 hasn't a move constructor
}

在main()行中,我希望调用移动分配和复制分配.但他们不知道!

MSVC2012输出是:

X默认构造函数调用X移动构造函数调用X默认构造函数调用X移动构造函数

而g++的一个是

X默认构造函数称为X默认构造函数

http://liveworkspace.org/code/220erd2美元

任务在哪里??我认为第一个main()行将调用一个移动赋值,而第二个main()行将调用一个复制赋值。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-04-02 18:21:43

代码语言:javascript
复制
// Constructor2
X2(X const& other): // copy constructor
    data(other.data)   // duplicate all that data
{}

X2& operator=(X const& other) // copy-assignment
{
    data=other.data; // copy all the data
    return *this;
}

首先,这些不是X2的复制构造函数和复制赋值操作符,因为它们接受X类型的参数。第一个实际上被称为转换构造函数,因为它可以从X转换为X2

代码语言:javascript
复制
int x = 5;

这不是分配给x的5;它是用5初始化的x。初始化,虽然看起来很相似,但与赋值不一样。实际上,代码中根本没有赋值,因此将不使用移动或复制赋值运算符。

我们可以看看您给出的每个编译器实际上在做什么:

  1. MSVC 首先,myNewObject是用make_x创建的。这个打印出了X default constructor called。然后,return myNewObject;将首先将返回值的副本视为一个移动,发现存在一个move构造函数,并调用它。 如果符合或将满足复制操作的省略条件,除非源对象是函数参数,并且要复制的对象由lvalue指定,则首先执行重载解析,以选择副本的构造函数,就好像对象是由rvalue指定的一样。

然后将返回值复制到x1中。但是,由于没有看到X copy constructor called输出,这个副本显然被省略了:

当没有绑定到引用(12.2)的临时类对象被复制/移动到具有相同cv非限定类型的类对象时,可以通过将临时对象直接构造到省略复制/移动的目标中来省略复制/移动操作。

其次,在对myNewObject的第二次调用中创建了另一个make_x。这再次打印出X default constructor called。然后,在执行return myNewObject时也会发生同样的情况。返回值的x2构造不会输出任何内容,因为它的构造函数接受X不会执行任何输出。

  1. GCC 首先,myNewObject是在make_x中创建的,与MSVC一样。这个打印出了X default constructor called。 现在GCC做了一个MSVC没有做的额外的优化。它意识到,它可能不会麻烦地从myNewObject移到返回值,而只是直接在返回值的位置构造它: 在具有类返回类型的函数中的返回语句中,当表达式是与函数返回类型相同的非易失性自动对象(函数或catch-子句参数除外)的名称时,可以通过将自动对象直接构造到函数的返回值中来省略复制/移动操作。

然后,从临时对象构造x1所引起的省略将与MSVC中的情况相同。

make_x的第二次调用与第一次调用完全相同,但现在x2是由接受X的转换构造函数构造的。当然,这没有输出任何东西。

票数 8
EN

Stack Overflow用户

发布于 2013-04-02 18:20:22

你看到了命名返回值优化,NRVO的效果。以下代码

代码语言:javascript
复制
X f()
{
  X tmp;
  // ...
  return tmp;
}

可以完全移除临时,并在函数调用方的返回槽中构造它。在您的示例中,效果就像函数是内联的,直接构造x1x2

如果你想看到任务,你可以写:

代码语言:javascript
复制
X x1;
x1 = make_x();
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15771356

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档