如何检查C ++中是否定义了变量,特别是指针?假设我有一个班级:
class MyClass {
public:
MyClass();
~MyClass() {
delete pointer; // if defined!
}
initializePointer() {
pointer = new OtherClass();
}
private:
OtherClass* pointer;
};
答案 0 :(得分:22)
为什么要担心检查指针值?只需将其初始化为空指针值,然后只需在其上调用delete即可。删除空指针什么都不做(标准保证它)。
class MyClass {
public:
MyClass():pointer(0) { }
~MyClass() {
delete pointer;
pointer = 0;
}
initializePointer() {
pointer = new OtherClass();
}
private:
OtherClass* pointer;
};
每次调用delete时,都应该将指针设置为空指针值。那你一切都很好。
答案 1 :(得分:8)
我倾向于在对象构造时将指针值初始化为NULL。这允许检查NULL以查看是否定义了指针变量。
答案 2 :(得分:6)
除了检查0
(NULL
)之外,还有一个解决方案是重构代码,以便强制指针始终有效。这并非总是可行,但在大多数情况下,这是最好的解决方案。
在您的情况下(与大多数其他情况一样),这意味着在构造函数中初始化指针(即,一旦其生命周期开始)并在其生命周期结束时销毁它。创建变量private
并且不允许对它进行直接写访问以确保它始终保持有效。
这是C ++中经常使用的模式,它有效地将指针对象的对象生命周期限制为类的生命周期。有时候,提供某种删除指针并立即重新初始化它的reset
也可能是一种可行的解决方案。如果这是以异常安全的方式编写的,那么您还确保指针永远不会无效。
不创建bool
ean标志以跟踪指针的有效性。将指针设置为0
。
答案 3 :(得分:4)
构造函数的重点是在完成所有成员变量之后才能正确定义。在这种情况下,NULL是有效的初始值。
明确定义了对NULL的调用。
更常见的是你希望构造函数定义RAW指针的值。另外,因为你的对象包含一个RAW指针并且显然拥有它(它正在删除它,这意味着所有权)你还必须确保覆盖编译器生成的Copy Constructor和Assignment Operator版本。
class MyClass
{
public:
MyClass()
:pointer(NULL) // valid value.
{}
~MyClass()
{
delete pointer; // This is fine.
}
void initializePointer() // Missing return type
{
pointer = new OtherClass();
}
private:
MyClass(MyClass const& copy); // If you don't define these
MyClass& operator=(MyClass const& copy);// two the compiler generated ones
// will do nasty things with owned
// RAW pointers.
OtherClass* pointer;
};
或者,您可以使用其中一个标准智能指针。可能是std :: auto_ptr<>除非你真的想让对象可以复制。
答案 4 :(得分:2)
您应该始终在构造函数中将指针初始化为NULL;这样你可以检查析构函数是否已经初始化。此外,在构造函数的参数列表中执行此操作更有效:
MyClass::MyClass() : pointer(NULL)
{
}
MyClass::~MyClass()
{
if(pointer != NULL) { delete pointer; }
}
同样,在删除它时,还应该将值设置为NULL,并在分配时将值检查为null,如果在程序的生命周期内将多次重新初始化对象。但是,在析构函数中将值设置为NULL不会产生任何差别,因为对象显然会被销毁。
这样做的好处(而不是在构造函数中显式地说“pointer = NULL;”)是编译器已经隐式为你做了这样的赋值。做一个手动分配会使它发生两次,这通常不是什么大问题,除非你在一个大循环中做了很多类的实例。
答案 5 :(得分:1)
你不能,我知道AFAIK。标准方法是在它不包含有效值时将其设置为NULL。在任何情况下,将指针都指向无效内存是不好的做法。如果您坚持这一点,您可以随时检查NULL以查看它是否“已定义”。
答案 6 :(得分:1)
真正的answer是轻微的,但我只想发表评论。使用智能指针(在本例中为std :: auto_ptr就足够了)可以解决问题,并且具有以下优点:您不需要记住在析构函数中删除指针。实际上,默认析构函数(由编译器生成)将处理内存资源。
使注释更加通用,您应该声明赋值运算符和复制构造函数标记为私有(并且未定义)或手动定义以避免指针的双重删除。编译器提供的运算符==和复制构造函数将只复制指针,最终你将进入双删除。我在这里写这个,因为如果你使用std :: auto_ptr,并在auto_ptr中添加了复制语义的奇怪性,那么这也是需要考虑的事情。
答案 7 :(得分:1)
另一个没有提到的答案是使用智能指针对象而不是原始指针。根据指针随后的使用方式,std::auto_ptr
,boost::shared_ptr
或许多其他智能指针类可能适合此处。如果您更改boost::scoped_ptr
的工作方式,initializePointer()
也可能有用。
这样智能指针就会记住它是否有效,并在包含对象被销毁时自行删除:
class MyClass {
public:
MyClass();
~MyClass() {
}
initializePointer() {
pointer.reset( new OtherClass());
}
private:
std::auto_ptr<OtherClass> pointer;
};