在解除引用新内容时移动语义和构造函数

时间:2016-06-01 08:38:11

标签: c++11 move-semantics

我有以下代码(http://coliru.stacked-crooked.com/a/a0e5ff6ee73634ee):

#include <iostream    

class A {
  public:
  explicit A(int a)         {std::cout << "Main constructor" << std::endl;}
  A(const A& a)             {std::cout << "Copy constructor" << std::endl;}
  A& operator =(const A& a) {std::cout << "Copy assignment" << std::endl; return *this;}
  A(A&& a)                  {std::cout << "Move constructor" << std::endl;}
  A& operator =(A&& a)      {std::cout << "Move assignemnt" << std::endl; return *this;}
};

int main(void) {
    std::cout << "\nA a3(A(0))" << std::endl;
    A a3(A(0));
    std::cout << "\nA a31(std::move(A(0)))" << std::endl;
    A a31(std::move(A(0)));
    std::cout << "\nA a4(*(new A(0)))" << std::endl;
    A a4(*(new A(0)));
    std::cout << "\nA a41(std::move(*(new A(0))))" << std::endl;
    A a41(std::move(*(new A(0))));
}

此代码编写以下内容:

A a3(A(0))
Main constructor  

- &GT;阅读Move semantics and copy constructor后,我假设发生了RVO,a3接管了A(0)构造的内容。

A a31(std::move(A(0)))
Main constructor
Move constructor   

- &GT;行

A a4(*(new A(0)))
Main constructor
Copy constructor    

- &GT;为什么这不是一个移动构造函数而不是Copy构造函数?

A a41(std::move(*(new A(0))))
Main constructor
Move constructor  

- &GT; OK
编辑: 在深入分析问题之后,我意识到实际上@sameerkn是对的。然而,正如@Angew所建议的那样,我试图用静态变量来分析正在发生的事情:这些变量没有像人们预期的那样被移动(它们似乎被视为const变量)。 看这里完整代码: http://melpon.org/wandbox/permlink/RCntHB9dcefv93ID

以下代码:

A a1(testStatic(1));
A a2(std::move(*(a1.getPointer())));  <-- Moving a dereference
std::cout << "\na1.mValue = " << a1.mValue << std::endl;
std::cout << "a2.mValue = " << a2.mValue << std::endl;

将返回:

Main constructor: This is my long String that should not be SSOed [STATIC]
Copy constructor: This is my long String that should not be SSOed [STATIC]
return aLocal
Move constructor  <-- The dereferenced pointer is moved as expected
Destructor: [mValue moved away]   <-- See here that the string was moved away
Move constructor  <-- Moved again because of std::move

2 个答案:

答案 0 :(得分:7)

A a4(*(new A(0)))
Main constructor
Copy constructor    
     

- &GT;为什么这不是一个移动构造函数而不是Copy构造函数?

因为取消引用指针会给出左值引用。指针本身是一个rvalue的事实不起作用 - 为什么要这样?你可以很容易地让一个rvalue指针指向一个绝对不是rvalue的东西。例如:

std::string s{"42"};

std::string* getPointer()
{
  return &s;
}

int main()
{
  std::string x(*getPointer());
  std::cout << s;
}

getPointer返回的指针是一个右值,就像new A返回的指针一样。但你肯定希望代码将s的内容移到x,你呢?

答案 1 :(得分:1)

new A(0);

通过&#34; new&#34;创建对象。 (注意:它创建一个纯对象,其身份可以通过&#34; new&#34;在代码中返回的地址来识别,并且该对象可以用于代码以供其使用,在任何意义上都不是临时的无名对象。)

将语义工作转移到纯粹的临时对象上,该对象的身份无法使用。