移动涉及const unique_ptr的构造函数

时间:2015-03-22 12:22:53

标签: c++ const move unique-ptr move-constructor

在下面的代码中,我创建了p const,因为在Foo的生命周期中它永远不会指向任何其他int。这不会编译,因为调用了unique_ptr的复制构造函数,这显然已被删除。除了使p非常数之外还有其他解决方案吗?感谢。

#include <memory>

using namespace std;

class Foo 
{
public:
  //x is a large struct in reality
  Foo(const int* const x) : p(x) {};
  Foo(Foo&& foo) : p(std::move(foo.p)) {};
private:
  const unique_ptr<int> p;
};

5 个答案:

答案 0 :(得分:5)

移动构造函数的语义是矛盾的。

您已声明const std::unique_ptr将(唯一)拥有初始化的值。 但是你已经宣布了一个移动构造函数,它应该将该值移动到构造中的另一个对象。

那么您认为临时&#39;中的std::unique_ptr会发生什么?从...构建移动

如果您希望它release(),则您违反了const。 如果您希望它保留其值,则您违反了std::unique的约束,只需要一个这样的对象来拥有任何给定的对象。 的将死。

这个问题揭示了C ++语言的一个微妙限制。它需要move语义才能将复制到作为有效对象。

对于“破坏性移动”有几个非常合理的建议。这实际上更好地反映了move的大多数用途正在做什么 - 从那里获取价值&#39;无效&#39;什么在那里。

谷歌他们。我没有做过文献调查,所以不想推荐一个。

此处的替代方法是删除const或将其删除。 我强烈建议删除它。你可以确保你班级的语义确保适当的持久性,没有任何影响,也没有“丑陋的怀疑”。 const_cast

#include <iostream>
#include <memory>

class Foo 
{
public:
  Foo(const int x) : p(new int(x)) {};
  Foo(Foo&& foo) :
    p(std::move(foo.p)) {

    };

    int get(void)const{
        return *(this->p);
    }

private:
     std::unique_ptr<int> p;
};

Foo getMove(){
    return Foo(88);
}

int main(){

    Foo bar(getMove());    
    std::cout<<bar.get()<<std::endl;

    return EXIT_SUCCESS;
}

答案 1 :(得分:2)

要理解您的代码无法编译的原因,请反映您已宣布Foo类的方式以及通常如何实现move semantics

声明const unique_ptr<T> p,你的意思是p本身永远不会被修改,但你仍然可以修改指向对象,因为T不是const。

move的作用相反。此功能使用允许从对象窃取资源并将其保留为空状态的想法(如果空状态有意义)。如果可能有用,请将move视为一种“破坏性”&#39;复制移动的对象。

std::move(foo.p),基本上你窃取foo.p指向的资源并将其保持在安全状态,这意味着将foo.p分配给NULL。但foo.p被声明为const,因此不允许进行操作。

请注意,在您的情况下,您不需要将p声明为const unique_ptr<int>。只需将其声明为unique_ptr<int>并确保成员函数声明为const,非成员函数将其视为const unique_ptr<int> p& p参数。通过这种方式,您可以确保{{1}}永远不会沿对象生命周期发生变化(移动操作除外)。

答案 2 :(得分:1)

使用std :: unique_ptr的概念表示对象的唯一所有权。你要实现的是让Foo类拥有一个对象(由std :: unique_ptr表示)使它成为可移动的(你的移动构造函数),这会产生矛盾。我会坚持使用std :: unique_ptr或使用std :: shared_ptr进行共享。

你可能想读这个: Smart Pointers: Or who owns you baby?

答案 3 :(得分:1)

这是因为int lastCol = r.Column; 只有move-constructor,这意味着unique_ptr的初始化参数不能是const,而p是const。我想你想要的是宣布

  

unique_ptr p;

而不是

  

const unique_ptr p;

p

答案 4 :(得分:0)

如果您想阻止所有权转让,可以使用const std::unique_ptr<T>。这不是很有用。

如果您想阻止修改它所拥有的对象,可以使用std::unique_ptr<const T>