【问题标题】:Move semantics and constructors when dereferencing a new取消引用 new 时移动语义和构造函数
【发布时间】:2016-06-01 08:38:11
【问题描述】:

我有以下代码 (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  

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

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

-> 好的

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

-> 为什么这不是移动构造函数而不是复制构造函数?

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

-> 好的
编辑: 在更深入地分析问题后,我意识到@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

【问题讨论】:

    标签: c++11 move-semantics


    【解决方案1】:
    A a4(*(new A(0)))
    Main constructor
    Copy constructor    
    

    -> 为什么这不是移动构造函数而不是复制构造函数?

    因为取消引用指针会提供左值引用。指针本身是右值这一事实没有任何作用——为什么要这样做?您可以很容易地拥有一个指向绝对不是右值的东西的右值指针。示例:

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

    getPointer 返回的指针是一个右值,就像new A 返回的指针一样。但您肯定不会期望代码将s 的内容移动到x,对吗?

    【讨论】:

    • 嗨@Angew,我将分辨率移动到sameerkn,因为从我写的EDIT 中,实际上可以移动取消引用的函数,但不是新的。您对静态的观点非常有趣。我添加了一个指向代码 sn-p 的链接,显示静态变量实际上是不可移动的(我曾预料到但从未读过)。
    【解决方案2】:
    new A(0);
    

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

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

    【讨论】:

    • 嗨@sameerkn,感谢您的评论。实际上 new 返回一个原始指针,这样的指针是 POD 类型 (en.cppreference.com/w/cpp/concept/PODType),因此不可移动。在问题中,我想知道为什么没有移动该指针的取消引用。
    • 我认为:"Not Movable" 的意思是“在地址空间中具有已知/可识别且可以使用的特定区域(地址)。” “可移动”是指“在运行时无法识别的临时空间/地址或程序中其他地方无法引用的临时对象”。通过 new 创建的对象不是临时的。
    • 嗨@sameerkn,感谢您的解释,正如我在编辑中写的那样,您的解释是正确的。
    猜你喜欢
    • 2013-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 2013-01-08
    • 1970-01-01
    • 2016-01-27
    • 2021-12-03
    相关资源
    最近更新 更多