C++ 私有(private)常量指针

标签 c++

我正在学习 C++ 中的指针,但遇到了一些麻烦。 我有一个类 Foo,它在头文件中声明了一些数据:

private:
const Bar *obj;

Bar 是一个类。

然后在 c++ 实现中我想替换 *obj 以便它指向一个完全不同的 Bar 对象。 *obj 是常量,那么如何更改 *obj 指向的内容,或者更确切地说,*obj 处内存中的内容?同样在 Foo 的析构函数中,我如何释放 *obj

最佳答案

给定你的类定义

class A {
private:
  const Bar *obj;
};

obj是指向常量 Bar 的指针目的。您可以更改该指针指向的内容,但不能更改所指向对象的内容。

所以,如果你有一个新的 Bar对象并且您想更改 obj所以它指向那个,你可以简单地分配新值:

/* New object: */
Bar *new_bar = new Bar;
/* Change the pointer: */
obj = new_bar;

但是,有两个问题。

  1. 如果新Bar对象是在类之外创建的,您不能直接将其分配给obj因为后者是私有(private)的。因此你需要一个 setter 函数:

    class A {
    private:
      const Bar *obj;
    public:
      void set_obj(const Bar *new_obj) { obj = new_obj; }
    };
    
  2. 您必须确定谁将最终拥有 Bar对象,即谁负责释放它占用的堆空间。如果来电者负责,那么您可以按上面的方式对其进行编码,即 class A永远不会创建新的 Bar对象,也不会删除任何对象。它只会维护一个指向 Bar 的指针。在类外创建和删除的对象。

    但是如果class A above 实际上负责 Bar 占用的内存空间对象,您必须使用 delete obj在析构函数中释放空间,并且在获得新的 Bar 时还必须释放空间分配的对象。即 set_obj上面的函数需要改成这样:

    void set_obj(const Bar *new_obj) { delete obj; obj = new_obj; }
    

    否则会发生内存泄漏。必须在复制构造函数(除非您删除它)以及赋值运算符中采取类似的措施:只要复制 class A 就会使用这两个函数。对象已创建,在这种情况下,您必须确保您不是简单地复制指针,而是分配新空间并复制对象(即您必须执行深复制):

    A(const A& a):obj(new Bar(*a.obj)) {}
    A& operator=(const A& a) { delete obj; obj = new Bar(*a.obj); return *this; }
    

    话虽如此,如果您的类负责内存空间,那么使用智能指针类而不是原始指针是一个好得多的想法。主要原因是: (i) 上述内容比较复杂,容易出错; (ii) 以上仍然不是很好——当抛出异常时,可能仍然存在内存泄漏或更糟糕的问题,例如在 Bar 的构造函数中. C++11 提供了一个名为 std::unique_ptr 的智能指针类,这似乎很适合您的目的:

    class A {
    private:
      std::unique_ptr<const Bar> obj;
    public:
      ~A() {}
      void set_obj(std::unique_ptr<const Bar> new_obj) { obj = new_obj; }
    };
    

    有了这个,智能指针将处理任何需要自动释放的内存空间,无论是在销毁时还是在新的 Bar 时。对象被分配给指针。

关于C++ 私有(private)常量指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13041496/

相关文章:

c++ - 从可能为 NULL 的字符指针初始化 std::string

C++ 分配器,特别是将构造函数参数传递给使用 boost::interprocess::cached_adaptive_pool 分配的对象

C++ 获取剪贴板 - 特殊字符

c++ - 为什么获取已声明函数的地址才有效?

c++ - 我们如何在 boost 属性树中获取对象

c++ - Magick++ 使用 CGI 显示图像

c++ - QLCDNumber 数字不能居中

c++ - 为什么必须在哪里放置 “template”和 “typename”关键字?

c++ - BOOST_CHECK_CLOSE 即使两个值低于阈值也会失败

c++ - 从动态链接库调用函数一次,从可执行文件调用一次