智能指针,this和构造函数

时间:2019-01-16 22:26:22

标签: c++ smart-pointers

  

简介::将下面第一段代码中的原始指针转换为智能指针,而其余功能保留为   尽可能保持不变。


我正在编写一些代码,试图将指针传递给对象的构造函数,目的是在构造函数返回时使该指针指向构造的对象。

(注意:这起源于一个更为复杂的情况,但我已将其简化为问题的本质。因此,如果您尝试询问为什么我正在这样做,在这种情况下不一定会找到明智的答案-但这不是问题的重点。)

在努力使用智能指针实现之后,我恢复了原始指针以确保没有遗漏一个基本问题:

#include <iostream>

class Thing {
 public: 
  Thing(int data, Thing* thing_ptr) {
    data_ = data;
    *thing_ptr = *this;
  }

  void PrintData() {
    std::cout << data_ << std::endl;
  }

 private:
  int data_;
};

int main() {
  Thing* thing_ptr;
  Thing t(6, thing_ptr);
  thing_ptr->PrintData();

  return 0;
}

顺利进行了,但是当我返回智能指针时,我似乎无法重现此功能。基本的问题是我不执行不必要的额外工作或无法正常工作,不知道如何初始化智能指针。

我尝试的第一件事是:

#include <iostream>
#include <memory>

class Thing {
 public: 
  Thing(int data, std::unique_ptr<Thing>& thing_ptr) {
    data_ = data;
    thing_ptr = std::unique_ptr<Thing>(this);
  }

  void PrintData() {
    std::cout << data_ << std::endl;
  }

 private:
  int data_;
};

int main() {
  std::unique_ptr<Thing> thing_ptr;
  Thing th(6, thing_ptr);
  thing_ptr->PrintData();

  return 0;
}
我认为

失败了(运行时发生核心转储),因为 this 实际上不是指向Thing的指针,而是指向未初始化的内存块的指针。容纳Thing的正确大小。实际上,我不是100%知道这里发生了什么,但是由于unique_ptrshared_ptr都失败了,我决定我应该首先初始化智能指针,然后分配 {{1} }

问题是我无法用这种方法创建一个额外的对象(这反过来甚至需要添加一个额外的构造函数)。

this

在这里我做一个 Thing() : data_(0) {} Thing(int data, std::unique_ptr<Thing>& thing_ptr) { data_ = data; if (!thing_ptr) { thing_ptr = std::make_unique<Thing>(); } *thing_ptr = *this; } 只是将其分配给下一行,这肯定不是正确的方法。

聪明的人可以向我指出正确的方向吗?

1 个答案:

答案 0 :(得分:3)

智能指针的最常见用法是管理对象的生存期。但是请注意,当您声明具有类类型的变量时,如

Thing th(6, thing_ptr);

对于该对象的生存期别无选择:如果在功能块中声明,它将在下一个封闭的}处结束,或者如果声明为类成员,则在包含对象的生存期结束时结束,如果声明为名称空间成员,则在程序末尾。 std::unique_ptr<T>使用默认删除器只能包含指向使用new创建的对象的指针,因为默认删除器会尝试使用delete

如果您的指针将始终指向具有此类普通声明的对象,而不是使用new创建的,则您必须自己确保仅在对象的生命周期内使用指针他们指着。在这种情况下,使用std::unique_ptr并不会获得太多优势;您可以继续使用原始指针,当其他问题(此处为C ++语言本身)引起生命周期问题时,它仍然是表示指针的常用方式。

如果您希望指针的寿命超过创建对象的功能块,则不能使用普通的对象声明语法。一种可能的选择是要求所有对象创建都使用create函数,而不是直接声明一个对象:

class Thing {
public:
    static std::unique_ptr<Thing> create(const Thing& src)
    { return { new Thing(src) }; }
    static std::unique_ptr<Thing> create(int data)
    { return { new Thing(data) }; }

    void PrintData() const;

private:
    // All constructors private, to make sure a Thing can ONLY be
    // created by a create() function - including the copy constructor.
    Thing(const Thing&) = default;
    explicit Thing(int data) : data_(data) {}

    int data_;
};

int main() {
    auto thing_ptr = Thing::create(6);
    thing_ptr->PrintData();
}