移动构造函数不被调用,而是调用复制构造函数

时间:2016-03-25 01:52:42

标签: c++ c++11 move-semantics move-constructor

我正在尝试调用move构造函数,但是调用了复制构造函数。 我做错了什么?

#include <iostream>
#include <string.h>

class X
{
    char* name;
public:
    X(const char* p)
    {
        name = new char[strlen(p) + 1];
        strcpy(name, p);
        std::cout<<"Constructor: "<<name<<"; Address: "<<this<<std::endl;
    }

    ~X()
    {
        std::cout<<"Destructor: "<<name<<"; Address: "<<this<<std::endl;
        delete [] name;
    }

    X(const X& a)
    {
        name = new char[strlen(a.name) + 1];
        strcpy(name, a.name);
        std::cout<<"Copy Constructor: "<<name<<"; Address: "<<this<<"; made from: "<<&a<<std::endl;
    }

    X& operator=(const X& a)
    {
        if (name)
        {
            delete [] name;
        }

        name = new char[strlen(a.name) + 1];
        strcpy(name, a.name);
        std::cout<<"Assignment operator: "<<name<<"; Address: "<<this<<"; made from: "<<&a<<std::endl;

        return *this;
    }

    X operator+(const X& a)
    {
        std::string s1 = name;
        std::string s2 = a.name;
        s1.append(" ");
        s1.append(s2);

        X x(s1.c_str());

        std::cout<<"operator+: "<<s1.c_str()<<"; Address: "<<&x<<"; Created from"
            <<this<<" and "<<&a<<std::endl;

        return x;
    }

    // move copy constructor
    X(X&& a)
    {
        name = a.name;
        a.name = nullptr;
        std::cout<<"Move Copy Constructor: "<<name<<"; Address: "<<this<<std::endl;
    }

    friend X fun(const X& a);
};

X fun(const X& a)
{
    std::cout<<"Inside fun()"<<std::endl;
    X p = a;
    return p;
}

int main()
{
    X h("Harry");
    X r("Ron");

    std::cout<<"Trying to create a temporary object"<<std::endl;
    X a = fun(h + r);
    std::cout<<"Check above if a temporay object was created"<<std::endl;

    return 0;
}

上述计划的O / P:

Constructor: Harry; Address: 0x79315dbc31b0
Constructor: Ron; Address: 0x79315dbc31c0
Trying to create a temporary object
Constructor: Harry Ron; Address: 0x79315dbc31e0
operator+: Harry Ron; Address: 0x79315dbc31e0; Created from0x79315dbc31b0 and 0x79315dbc31c0
Inside fun()
Copy Constructor: Harry Ron; Address: 0x79315dbc31d0; made from: 0x79315dbc31e0
Destructor: Harry Ron; Address: 0x79315dbc31e0
Check above if a temporay object was created
Destructor: Harry Ron; Address: 0x79315dbc31d0
Destructor: Ron; Address: 0x79315dbc31c0
Destructor: Harry; Address: 0x79315dbc31b0

是否意味着程序无法创建临时对象? 我以为地址为0x79315dbc31e0的对象是一个临时对象。

注意:由于我的gcc已经老了,我在其中一个支持C ++ 11和C ++ 14的在线C ++编译器上尝试了这段代码。

1 个答案:

答案 0 :(得分:2)

在“Inside fun()”之后立即调用“复制构造函数”实际上是从fun()中的以下行调用复制构造函数:

X p = a;

这是对复制构造函数的调用。您显然期望由于以下原因而调用移动构造函数:

X a = fun(h + r);

这个临时性被完全“消除”了。整个序列:

X p = a;
return p;

结果在编译器中基本上构造p作为函数的返回值,因此“return p”什么都不做。

然后,因为函数的返回值用于实例化main()中的a对象,所以调用者实际上将main()的“a”传递给fun(),作为由fun()构建的对象。

只需使用调试器逐步执行代码,就可以亲眼看到这些事件的顺序。