我正在学习c ++指针,但遇到了一些麻烦。
我有一个类Foo
,在头文件中声明了一些数据:
private:
const Bar *obj;
Bar
是一个类。
然后在c ++实现中,我想替换*obj
,以便它指向一个完全不同的Bar
对象。 *obj
是不变的,那么如何更改*obj
指向的内容,或者更改*obj
内存中的内容?同样在Foo
的析构函数中,如何解除分配*obj
?
答案 0 :(得分:4)
鉴于你的班级定义
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
,因为后者私有。因此,您需要一个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
实际上负责Bar
个对象占用的内存空间,则必须在析构函数中使用delete obj
来释放空间,并且还必须释放分配新的Bar
对象时的空格。也就是说,上面的set_obj
函数需要更改为:
void set_obj(const Bar *new_obj) { delete obj; obj = new_obj; }
否则你会有内存泄漏。必须在复制构造函数中执行类似的度量(除非将其删除),以及赋值运算符:每当class A
对象的 copy 生成时,都会使用这两个函数,并且在这种情况下,您必须确保不是简单地复制指针,而是分配新空间并复制对象(即您必须执行深层复制):
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
对象分配给指针时。
答案 1 :(得分:1)
你不能使用那个指针来改变被指向的值,这就是为什么它是一个const,但你应该能够改变它所指向的内容。
答案 2 :(得分:1)
在c ++上“const Bar * obj;”意味着你有一个指向只读Bar对象的指针;意思是你可以将它指向任何只读Bar对象。
您还可以指向非常量变量,因此承诺不会使用该指针更改它。
如果你想要一个指针,那就是它不能指向任何其他东西,那么你应该这样写:
Bar * const obj = some_object;
这将编译并正常工作:
const int p = 1, q = 2;
int r = 3;
const int* i = &p;
i = &q; // point it to a different const variable.
i = &r; // point it to a different non const variable.
答案 3 :(得分:0)
正如所写,我相信这是一个指向const Bar对象的指针,而不是一个常量指针。