c++ - 智能指针、this 和构造函数

标签 c++ smart-pointers

Synoposis: convert the raw pointers in the first block of code below to smart pointers while leaving the rest of the functionality as unchanged as possible.


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

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

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

#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 都失败了,我决定我应该首先初始化智能指针,然后分配 < strong>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;
  }

这里我创建了一个 Thing::Thing() 只是为了将它分配到下一行,这当然不是正确的方法。

有人聪明能给我指出正确的方向吗?

最佳答案

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

Thing th(6, thing_ptr);

您无法选择该对象的生命周期:它将在下一个封闭的 } 结束。如果在功能 block 中声明,或者如果声明为类成员,则包含对象的生命周期结束,或者如果声明为 namespace 成员,则在程序结束时。 std::unique_ptr<T>使用默认删除器只能包含指向使用 new 创建的对象的指针, 因为默认删除器尝试使用 delete .

如果您的指针将始终指向具有像这样的普通声明的对象,而不是使用 new 创建的对象,那么你就只能自己确保指针只在它们指向的对象的生命周期内使用。在这种情况下,使用 std::unique_ptr 并没有太大优势。 ;您可以继续使用原始指针,当其他东西(这里是 C++ 语言本身)负责生命周期问题时,这仍然是表示指针的普通方法。

如果希望指针的生命周期超过创建对象的功能 block 的可能性,则不能使用普通的对象声明语法。一种可能的替代方法是要求所有对象创建都使用 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();
}

关于c++ - 智能指针、this 和构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54226343/

相关文章:

c++ - 期望一个类型,得到一个模板

c++ - 手动对象所有权与智能指针

c++ - 霍夫曼编码

c++ - 如何将一个字符的用户输入存储到 C++ 中数组的每个元素中?

c++ - 为什么 virtual void test()=00 有效但 virtual void test()=+0 和 virtual void test()=-0 无效?

c++ - 如何围绕C 'class'概括此C++包装器?

用于双向随机访问的 C++ 高效数据结构

c++,将任何类型(模板T)的数据打印到控制台

使用 c 库的 C++ 程序 - 将智能指针转换为原始 c 样式指针?

c++ - 如何通过 std::unique_ptr 成员调用其他类的 const 成员函数