在C++的这一段中,delete this讨论了构造的使用.列出了4个限制.
限制1到3看起来很合理.但是为什么限制4在那里我"必须不检查它,将它与另一个指针进行比较,将它与NULL进行比较,打印它,投射它,用它做任何事情"?
我的意思this是又一个指针.为什么我不能把reinterpret_cast它int或者叫它printf()输出它的值?
有没有什么好的理由(除了"宏是邪恶的",也许)不使用以下宏?
#define DELETE( ptr ) \
if (ptr != NULL) \
{ \
delete ptr; \
ptr = NULL; \
}
#define DELETE_TABLE( ptr ) \
if (ptr != NULL) \
{ \
delete[] ptr; \
ptr = NULL; \
}
Run Code Online (Sandbox Code Playgroud) 我对Boost的侵入式指针有一个问题.它是布尔转换运算符检查x.get() != 0.但是,下面的代码在标记点处失败.为什么会这样?
我猜我可能与delete没有设置指针0(或nullptr)的事实有关.如果不是这样,我怎么能有效地使用侵入式指针?我希望能够使用像常规指针这样的侵入式指针,例如,在表达式中x && x->foo(),但这个人工制品似乎排除了它.
#include <atomic>
#include <boost/intrusive_ptr.hpp>
struct T
{
T() : count(0u) { }
size_t ref_count()
{
return count;
}
std::atomic_size_t count;
};
void intrusive_ptr_add_ref(T* p)
{
++p->count;
}
void intrusive_ptr_release(T* p)
{
if (--p->count == 0u)
delete p;
}
int main()
{
boost::intrusive_ptr<T> x;
x = new T;
assert(x->ref_count() == 1);
auto raw = x.get();
intrusive_ptr_add_ref(raw);
intrusive_ptr_add_ref(raw);
assert(x->ref_count() == 3);
intrusive_ptr_release(raw);
intrusive_ptr_release(raw); …Run Code Online (Sandbox Code Playgroud) 我们只能取消引用有效的指针,并且只能检查悬空内置指针指向的地址。我们无法访问它的值(它指向的对象地址中的值)。
int* ptr = nullptr;
if(ptr) // != 0x00000000
std::cout << *ptr << '\n';
ptr = new int(1000);
if(ptr) // != 0x00000000
std::cout << *ptr << '\n';
delete ptr; // still pointing at the address of that dynamic object but that object has been destroyed.
if(ptr) // succeeds or undefined behavior?
std::cout << *ptr << '\n'; // of course UB here
Run Code Online (Sandbox Code Playgroud)
所以我很清楚,但我关心的只是检查指针值是否安全或产生 UB?if(ptr)。因为我们假设我没有像 那样访问该地址中的值std::cout << *ptr。
我在 CPPCon 上看过一个演讲,back to basic: class layout链接是这个。在 54:20,他说两次删除 nullptr 是未定义的行为。据我所知,C++ 标准保证删除 nullptr 没有任何作用,但为什么删除 nullptr 两次是未定义的行为?
之前有人告诉我,不需要检查析构函数中的 ptr 是否为空,因为删除空指针是有效的。但是如果两次删除一个空指针是未定义的,这是否意味着我仍然需要检查它是否为 nullptr 以防止发生双重删除?
这是作者从他的视频中的转录:
[...] 忽略标准,然后又遇到了问题。我看到的一个常见示例是可以删除空指针,这很好,但是如果不将值重置为某个有效指针值,就不能删除它两次。如果我删除相同的指针两次,如果它不是空的,你可能会得到一个段错误,如果它是空的,它通常只是碰巧工作,但不能保证工作,实际上在 1980 年代有一个编译器在那里它不会工作,因为当您删除指针时,删除的指针中会覆盖一个新值。因此,再次遵循标准。
如果我delete指针如下,例如:
delete myPointer;
Run Code Online (Sandbox Code Playgroud)
而且,在这之后也没有分配0如下指针:
myPointer = 0; //skipped this
Run Code Online (Sandbox Code Playgroud)
会myPointer指向另一个内存地址吗?
在C++中:
const size_t N = 1000;
int* p = new int[N];// time=t0
Run Code Online (Sandbox Code Playgroud)
我的程序只有一个线程,在分配内存后p,我的程序只会读取指向的内存p.
标准对价值的评价是p什么?
将p保持,直到它得到在时间价值= T0 delete的p?
或者,操作系统可以自行决定重新分配指向的内存p吗?
它取决于价值N吗?
Object *p = new Object();
delete p;
Run Code Online (Sandbox Code Playgroud)
当我删除p时,删除堆上的对象分配.但是p本身究竟发生了什么?它是从堆栈中删除的吗?或者它仍然在堆栈中仍然包含以前保存对象的内存的地址?
如果我有一个指针指向堆上的特定内存地址.我想这同样的指针指向另一个内存地址,我应该先delete指针?但是,在这种情况下,我实际上是删除指针还是只是破坏指针指向的引用(内存地址)?
所以,换句话说,如果我delete是一个指针,这是否意味着它不再存在?或者,它在那里,但没有指出它在哪里?
在下面的代码中,为什么指针保持的地址x在delete?之后改变?据我所知,delete调用应该从堆释放已分配的内存,但它不应该更改指针地址.
using namespace std;
#include <iostream>
#include <cstdlib>
int main()
{
int* x = new int;
*x = 2;
cout << x << endl << *x << endl ;
delete x;
cout << x << endl;
system("Pause");
return 0;
}
OUTPUT:
01103ED8
2
00008123
Run Code Online (Sandbox Code Playgroud)
观察:我使用的是Visual Studio 2013和Windows 8.据说这在其他编译器中不起作用.此外,我理解这是不好的做法,我应该在删除指针后重新指定NULL,我只是想了解是什么驱使这种奇怪的行为.