简体   繁体   English

移动涉及 const unique_ptr 的构造函数

[英]Move constructor involving const unique_ptr

In the code below, I made p const because it will never point to any other int during Foo's lifetime.在下面的代码中,我设置了 p const 因为它在 Foo 的生命周期内永远不会指向任何其他 int。 This doesn't compile, as the unique_ptr's copy constructor is called, which is obviously deleted.这不会编译,因为调用了 unique_ptr 的复制构造函数,这显然被删除了。 Are there any solutions besides making p non-const?除了使 p 非常量之外,还有其他解决方案吗? Thanks.谢谢。

#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;
};

The semantics of your move constructor are contradictory.您的移动构造函数的语义是矛盾的。

You have declared a const std::unique_ptr which will (uniquely) own the value it is initialised with.您已经声明了一个const std::unique_ptr ,它将(唯一地)拥有它初始化的值。 But you've declared a move constructor that should move that value into another object at construction.但是您已经声明了一个移动构造函数,它应该在构造时将该值移动到另一个对象中。

So what do you think should happen to the std::unique_ptr in the 'temporary' being move constructed from?那么,您认为构造移动的“临时”中的std::unique_ptr应该发生什么?

If you want it to be release() ed you've violated its const ness.如果你希望它是release() ed,你就违反了它的const If you want it to retain its value you've violated the constraint of std::unique which requires no more than one such object to own any given object.如果您希望它保留其值,则违反了std::unique的约束,该约束要求不超过一个此类对象拥有任何给定对象。 Checkmate.将死。

This problem reveals a subtle limitation of the C++ language.这个问题揭示了 C++ 语言的一个微妙的限制。 It requires move semantics to leave the copied to and from as valid objects.它需要move语义才能将复制对象保留为有效对象。

There are several quite reasonable proposals for 'destructive move' which would in truth better reflect what most uses of move are doing - take a value to here from there 'invalidating' what was there.关于“破坏性移动”有几个相当合理的建议,实际上它们可以更好地反映move的大多数用途正在做的事情——从那里“使”那里的东西“无效”。

Google them.谷歌他们。 I haven't made a literature survey so don't want to recommend one.我没有做过文献调查,所以不想推荐一个。

Your alternatives here are to remove const or cast it way.您在这里的替代方法是删除const或强制转换。 I strongly recommend removing it.我强烈建议删除它。 You can make sure the semantics of your class ensure the appropriate const-ness with no impact and no 'ugly suspect' const_cast .您可以确保类的语义确保适当的 const-ness 没有影响,也没有“丑陋的嫌疑人” 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;
}

To understand why your code does not compile, reflect how you have declared Foo class and how move semantics is generally implemented.要了解为什么您的代码无法编译,请反映您如何声明Foo类以及通常如何实现move semantics

Declaring a const unique_ptr<T> p , you mean that p itself will be never modified, but you could still modify the pointed-to object because of T is not const.声明一个const unique_ptr<T> p ,你的意思是p本身永远不会被修改,但你仍然可以修改指向的对象,因为T不是 const。

But move works on an opposite assumption.但是move在相反的假设上起作用。 This feature uses the idea that is allowed stealing resources from objects and leave them in a empty state (if an empty state make sense).此功能使用允许从对象中窃取资源并将它们保持在空状态(如果空状态有意义)的想法。 If can be useful, think move as a sort of 'destructive' copy for the moved object.如果可能有用, move视为移动对象的一种“破坏性”副本。

Writing std::move(foo.p) , basically you steal the resource pointed by foo.p and leave it in a safe state, that means assign foo.p to NULL .编写std::move(foo.p) ,基本上你窃取了foo.p指向的资源并将其置于安全状态,这意味着将foo.p分配给NULL But foo.p was declared as const, so the operation is not permitted.但是foo.p被声明为 const,因此不允许该操作。

Please consider that in your case you don't need to declare p as a const unique_ptr<int> .请考虑,在您的情况下,您不需要将 p 声明为const unique_ptr<int> Simply declare it as unique_ptr<int> and make sure that member functions are declared as const and non-member functions take it as const unique_ptr<int> p& parameter.只需将其声明为unique_ptr<int>并确保将成员函数声明为const而非成员函数将其作为const unique_ptr<int> p&参数。 In this way you are sure that p will never change along the object lifetime (except in case of move operation).通过这种方式,您可以确定p在对象生命周期内永远不会改变(移动操作除外)。

It is because unique_ptr has only the move-constructor, which means the initialization argument to p cannot be const, while p is const.这是因为unique_ptr只有 move-constructor,这意味着p的初始化参数不能是 const,而p是 const。 I think what you wanted was to declare我想你想要的是声明

unique_ptr p; unique_ptr p;

instead of代替

const unique_ptr p;常量 unique_ptr p;

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;
};

Concept of using std::unique_ptr is representing a sole ownership of an object.使用 std::unique_ptr 的概念表示对象的唯一所有权。 What you're trying to achieve is having a Foo class own an object (which is expressed by std::unique_ptr) and making it movable (your move constructor) which makes a contradiction.您想要实现的是让 Foo 类拥有一个对象(由 std::unique_ptr 表示)使其可移动(您的移动构造函数),这会产生矛盾。 I would stick with std::unique_ptr or make it shared using std::shared_ptr.我会坚持使用 std::unique_ptr 或使用 std::shared_ptr 共享它。

You might want to read this: Smart Pointers: Or who owns you baby?您可能想阅读以下内容: 智能指针:或者谁拥有您的宝贝?

If you want to prevent transfer of ownership, you can use a const std::unique_ptr<T> .如果要防止所有权转移,可以使用const std::unique_ptr<T> This is not very useful.这不是很有用。

If you want to prevent modifying the object it holds, you can use a std::unique_ptr<const T> .如果你想防止修改它持有的对象,你可以使用std::unique_ptr<const T>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 c ++ unique_ptr移动构造函数 - c++ unique_ptr move constructor 使用unique_ptr &lt;&gt;实现移动构造函数和赋值 - Implementing move constructor and assignment with unique_ptr<> unique_ptr成员,私有拷贝构造函数与移动构造函数 - unique_ptr member, private copy constructor versus move constructor 使用 unique_ptr 移动调用对等构造函数的默认构造函数 - Default constructor that calls peer constructor with unique_ptr move `unique_ptr &lt;T const []&gt;`应该接受`T *`构造函数参数? - Should `unique_ptr< T const [] >` accept a `T*` constructor argument? 使const unique_ptr然后尝试从它移动std :: move会产生与尝试访问复制构造函数时相同的错误 - Making a const unique_ptr then trying to std::move from it gives the same error as if you were trying to access the copy constructor 为什么我们需要对unique_ptr的vector进行移动构造? - Why do we need a move constructor for vector of unique_ptr? 移动 std::unique_ptr 的构造函数/赋值:memory 重新分配? - move constructor/assignment of std::unique_ptr: memory reallocation? 在unique_ptr中包装一个没有移动构造函数的C++对象? - Wrap a C++ object without move constructor in a unique_ptr? 使用unique_ptr成员编写移动构造函数的正确方法(崩溃) - Correct way to write move constructor with unique_ptr member (crash)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM