【发布时间】:2016-07-12 19:01:41
【问题描述】:
我正在尝试调用移动构造函数,但正在调用复制构造函数。 我做错了什么?
#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++ 编译器之一上尝试了此代码。
【问题讨论】:
-
h + r的返回值是一个临时对象。输出有什么意外?你认为你在哪里“试图调用移动构造函数”? -
我期待“X a = fun(h + r);”调用移动复制构造函数。
-
在该行中,
a从fun的返回值中移出,但这也是一个复制省略上下文。X p内部的fun被标识为X a = fun(h+r);。如果您在禁用复制省略的情况下进行编译,您应该会看到移动构造函数调用。 -
@Saket
a指定一个临时对象,但a是一个左值(所有命名变量都是左值),所以X&&不会绑定到它。 (右值引用不能绑定到左值)。此外,您不能通过编写p = std::move(a);来解决此问题,因为a被声明为const。如果要移出临时对象,则不能将 const 引用绑定到临时对象。您将不得不改用X fun(X a);(可以使用左值和右值调用fun)或X fun(X&& a);(只能使用右值调用fun)。 -
您还需要将
X p = a;更改为X p = std::move(a);。我们正在考虑的复制省略位于return p;中。最初你说你认为X a = fun(h+r)是移动操作,但现在你说你认为它是X p = a;
标签: c++ c++11 move-semantics move-constructor