我正在学习 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;
但是,有两个问题。
如果新
Bar
对象是在类之外创建的,您不能直接将其分配给obj
因为后者是私有(private)的。因此你需要一个 setter 函数:class A { private: const Bar *obj; public: void set_obj(const Bar *new_obj) { obj = new_obj; } };
您必须确定谁将最终拥有
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/