C ++如何将对象移至nullptr

时间:2019-04-02 21:53:27

标签: c++ c++11 pointers move

我正在考虑一个奇怪的用例,其中我想将对象移至nullptr。也许我应该给一个代码片段:

class Objpair {
   public:
      Objpair(Obj&& a, Obj&&b) : first(&a), second(&b) { }
   private:
       Obj* first;
       Obj* second;
};

问题在于,当a和b超出范围时,第一个和第二个指针将悬空。如果我可以将Object a移到第一个指针上,那么应该就不会出现双重释放和作用域问题。如果首先将成员声明为Obj而不是Obj *指针,则直接的first(std :: move(a))将完成此工作。我在这里一定做错了。我正在考虑移动而不是复制,因为我试图将控制权从另一个对象转移到当前对象并提高性能。

使用指针版本是因为我正在考虑成员对象的多态行为。

4 个答案:

答案 0 :(得分:5)

您可以做的是从您的参数中移动构造对象,如下所示:

class Objpair {
   public:
      Objpair(Obj&& a, Obj&& b)
      : first(new Obj(std::move(a)))
      , second(new Obj(std::move(b)))
      {}

   private:
       Obj* first;
       Obj* second;
};

我建议您使用std::unique_ptr

class Objpair {
   public:
      Objpair(Obj&& a, Obj&& b)
      : first(std::make_unique<Obj>(std::move(a)))
      , second(std::make_unique<Obj>(std::move(b)))
      {}

   private:
       std::unique_ptr<Obj> first;
       std::unique_ptr<Obj> second;
};

答案 1 :(得分:2)

您不能将对象移动到指针(nullptr或其他)上。也不能通过使指针指向对象来延长对象的生存时间-C ++根本无法那样工作。

由于需要多态行为,因此不能只复制构造或分配Obj指针。您可能想要类似clone()Obj的{​​{1}}方法,如本问题所述:

Copying derived entities using only base class pointers, (without exhaustive testing!) - C++

有关此的更多信息。不过请记住,您无法延长右值引用的寿命,因此必须以某种方式构造一个新对象。还记得避免内存泄漏。因此,如果您的clone()产生了Obj*,则需要编写如下内容:

class Objpair {
   public:
      Objpair(Obj&& a, Obj&&b) : 
         first(a.clone()), 
         second(b.clone()) 
      { }
   private:
      std::unique_ptr<Obj> first;
      std::unique_ptr<Obj> second;
};

可能是std::shared_ptr,而不是unique_ptr(有关在两者之间进行选择,请参见this answer)。

如果您需要“多态”行为,但是您知道a和b在编译时的确切类型,并且您不介意拥有不同的ObjPair类,则可以也尝试这样的事情:

template <typename T1, typename T2>
class Objpair {
   public:
      Objpair(T1&& a, T2&&b) : first(a), second(b) 
      { }
   private:
      T1 first;
      T2 second;
};

在这种情况下,不涉及任何指针(!)

答案 2 :(得分:2)

您在评论中说,

  

第一和第二个可以指向BaseClass,Derived1,Derived2,

在这种情况下,最好的选择是在virtual中提供一个Obj成员函数来克隆对象。

class Obj
{
   public:
      virtual Obj* clone() const = 0;
   ...
}

并使用它来初始化firstsecond

 class Objpair {
   public:
      Objpair(Obj&& a, Obj&&b) : first(a.clone()), second(b.clone()) { }
   private:
       Obj* first;
       Obj* second;
};

,并确保您要在析构函数中分配由firstsecond指向的内存。有关更多详细信息,请参见The Rule of Three

您可以使用智能指针消除类中用于管理对象寿命的代码的需求。使用std::unique_ptr还是std::shared_ptr取决于您希望使用Objpair的方式。

答案 3 :(得分:0)

@Galik接受的答案很好。尽管它要求Obj至少是可移动的,这与Clone()解决方案的其他答案类似-它们都对Obj及其子代提出了一些要求。要消除此限制,我们可以将Objpair的构造函数更改为接受std::unique_ptr<Obj>

#include <memory>

class Obj
{
public:
    Obj() {}

    // non-copyable/non-movable
    Obj(const Obj&) = delete;
    Obj& operator=(const Obj&) = delete;
};

class Objpair {
   public:
      Objpair(std::unique_ptr<Obj>&& a, std::unique_ptr<Obj>&& b)
      : first(std::move(a))
      , second(std::move(b))
      {}

   private:
       std::unique_ptr<Obj> first;
       std::unique_ptr<Obj> second;
};

int main()
{
    Objpair p{std::make_unique<Obj>(), std::make_unique<Obj>()};
    return 0;
}

可能的奖金是:

  • 用户处理内存分配,因此可以更好地控制它。
  • 用户可以先将ab参数的实例多态传递给Objpair