你能判断一个c++指针是否被销毁了吗?
Can you tell if a C++ pointer has been destructed?
我有一个全局单例,它被我的程序中的许多对象使用。当程序关闭时,这会导致崩溃——它在一些对象的析构函数中使用,在单例本身被程序结束时被析构。是否有一种可移植的方法来判断指针是否有"删除"调用?在我的例子中,它看起来像是delete将指针的值更改为(void*)(-1),但我不知道这是否可移植。
不能,不能判断c++指针所指向的对象是否已被销毁。
你可以使用智能指针,它会自动处理。
简单回答:
- 不要使用指针
- 使用经典的Myers单例。
然后要保证它在对象之后被销毁,只需确保它在对象之前被实例化。要确保在对象之前实例化它,只需在对象的构造函数中使用它。
经验法则:如果你想在析构函数中使用单例。首先在构造函数中使用它。
class A
{
A();
A(A const&);
A& operator=(A const&);
public:
static A& getInstance() // return reference.
{
static A instance; // Created on first use.
// So lazily created when expensive.
return instance; // Guaranteed to be destroyed in reverse order of
// creation In comparison to other static storage
// duration objects. Thus if it is created before
// your object It is guaranteed to be correctly
// destroyed after your object.
// If you want to guarantee it is created before your
// object just call A::getInstance() in your constructor
// the static member 'instance' will only be created
// once and returning a reference is not expensive.
}
// If you are creating this from the constructor of a global
// Then threading becomes a non issues as threads are not started before main
// If you are using pthreads or Windows threads you potentially can start them
// but it is undefined if they will work so again not your issue.
};
不可能,我也会认为这是一个未定义的区域。
你最好的办法是在其他所有东西都被清理干净之前不要删除你的单例,否则在删除实例后将指针设置为NULL,然后你可以检查它。在我看来,一些重构是有序的。
正如已经说过的,不,你不能。有不同的技术来跟踪这一点,但它们是依赖于平台的。
首先,你的实际问题是什么?你有一个单例,它被其他对象销毁时使用。如果你的单例被C运行时销毁了,那么是什么销毁了其他对象呢?判断是什么在删除单例的简单方法是将单例的析构函数设为private。然后,您应该在试图删除它的任何地方得到编译错误。
这段代码将跟踪静态实例的生命周期;如果使用堆分配,效果同样好。当然,即使实例还没有构造,它也会在第一次调用instance()
时出现。然而,如果你有一些复杂的全局静态析构函数,你应该能够使用它来确定实例是否已经被析构。
class Thing
{
public:
enum State { preConstruction, constructed, destructed };
static const State& singletonState() { return state_;}
static Thing& instance()
{
static Thing instance;
return instance;
}
private:
Thing()
{
state_ = constructed;
}
~Thing()
{
state_ = destructed;
}
static State state_;
};
Thing::State Thing::state_ = Thing::preConstruction;
另一种选择是在调用delete
后,将指针设置为NULL
。然后,您可以检查指针是否为NULL
,并知道该指针已被删除(或尚未初始化)。
class MyClass
{
public:
MyClass()
{
pPointer = new NewClass();
}
~MyClass()
{
delete pPointer;
pPointer = NULL;
}
private:
NewClass *pPointer;
}
如果对象定义在单独的文件中,则c++没有定义调用两个全局构造函数或析构函数的顺序。然而,如果对象是在同一个文件中定义的,那么就有一个顺序:文件作用域对象是按词法顺序(它们在文件中出现的顺序)构造的,并按相反的顺序销毁。
这可以与头文件依赖关系结合使用,使c++全局构造和销毁变得有序,如下所示:
// header file A.h
#ifndef A_H_INCLUDED
#define A_H_INCLUDED
class A { /* ... */ };
#ifdef DEFINE_GLOBALS
A a_singleton;
#endif
#endif
// header file B.h
#ifndef B_H_INCLUDED
#define B_H_INCLUDED
#include "A.h"
class B : { A *pa_memb; /* ... */ }
#ifdef DEFINE_GLOBALS
B b_singleton;
#endif
#endif
// header file C.h
#ifndef C_H_INCLUDED
#define C_H_INCLUDED
#include "B.h"
#include "A.h"
class C : { A *pa_memb, B *pb_memb; /* ... */ }
#ifdef DEFINE_GLOBALS
C c_singleton;
#endif
#endif
然后,我们有一个名为globals.cc
的文件,我们这样做:
// globals.cc
#define DEFINE_GLOBALS
#include "C.h"
#include "A.h"
#include "B.h"
头文件中的#include
守卫将确保global.cc
中的包含符合正确的依赖顺序(并且丢失的可能会被拾取:在上面的示例中,如果我们只包含"C.h"
,我们就很好)。现在,所有的全局对象都在一个翻译单元中定义,并按照正确的顺序构造:使用的对象在其用户之前构造,在其用户之后销毁。
- std::vector::迭代器是否可以合法地作为指针
- 是否可以将llvm::FunctionType转换为C/C++原始函数指针
- 返回指向对象的指针的函数调用是否为 prvalue?
- 对象初始化中是否允许指向此成员的指针?
- 新分配指向函数的指针是否合法?
- 在函数结束后使用指向变量的指针是否安全?
- C++默认情况下,指针类型数组的元素是否保证初始化为 nullptr?
- 在对象指针上调用 Delete 是否会递归删除其动态分配的成员
- 如果整数与指针大小相同,则重新解释将整数转换为指针双射是否具有双射作用?
- 是否可以使用函数指针调用虚拟析构函数?
- std::less是否应该允许在编译时比较不相关的指针?
- 是否允许编译器省略对指针的 &* 运算符的组合调用?
- 将相同共享指针的副本存储在不同的向量中是否是一种好的做法?
- C++ 返回指向函数内定义的静态数组的指针是否有效?
- 检查输入 std::array 指针数据是否等于某个常量数组
- 成员访问是否在空指针上定义C++?
- 如果只有 std::auto_ptr 可用,我是否仍应该使用智能指针?
- 是否可以使用指针访问变量以避免直接编辑变量?
- 是否可以仅通过将分配的指针地址存储在C++中来分析内存?
- "this"指针的值在对象的生存期内是否恒定?