将对象设置为 NULL 和使用 ZeroMemory 到底有什么区别?
我听说在 WinAPI(主要是 C)中,一个人应该在 C 对象上使用 ZeroMemory 是一种很好的做法。我来自 C# 背景,这似乎是一个 C++ 人应该知道的。
我发现使用 DirectX API,无论您是否对对象进行了 ZeroMemory,应用程序仍然可以工作,但有些示例使用 ZeroMemory,有些则没有。
任何人都可以澄清这些事情吗?
ZeroMemory
用零填充一块内存。
将指针设置为 NULL 只会使指针指向空,这与用零填充指针指向的内存不同(例如,您仍然可以通过该指针访问该内存)。
在你可以对该对象做任何有用的事情之前,你可能需要用更有意义的东西替换这些零 - 这就是为什么两个程序都使用ZeroMemory
或不工作的原因。
在这种情况下的原因ZeroMemory
是您可以轻松找到在访问点未初始化的对象上的操作(例如,Visual Studio 正在使用0x0c0c0c0c
/* 或类似的 */ 填充未初始化的内存,因此当您在调试过程中遇到这种模式时,您知道该对象尚未初始化)。
这是完全不同的事情。ZeroMemory 宏用零填充一块内存。将指针设置为 NULL ......好吧,它使它指向无处。
例子。假设您有指向“Type”类型p
对象的指针:o
struct Type
{
int i;
float f;
bool b;
};
Type o;
Type* p = &o;
// In memory that will be something like this:
// "o" internals = [010101010001010010110010010010100011001001010000011...]
// "p" address = 0x00830748
//(number of bits and hex adress is just example)
如果你ZeroMemory
这样做:
ZeroMemory(&o, sizeof(o));
// ---- or -----
ZeroMemory(p, sizeof(o));
// In memory we will have:
// "o" internals = [000000000000000000000000000000000000000000000000000...]
// "p" address = 0x00830748
里面的所有变量o
现在的值都为零:
cout << o.i; // 0
cout << o.f; // 0.0f
cout << o.b; // false
cout << p->i; // 0
cout << p->f; // 0.0f
cout << p->b; // false
如果你NUll
-ify 指针:
p = NULL;
// In memory we now have:
// "o" internals = [010101010001010010110010010010100011001001010000011...]
// "p" address = 0x00000000
如果现在取消引用p
,您将获得未定义的行为:
int a = p->i; // Access voilation reading location 0x00000000
如果你NUll
-ify 对象:
它不会编译,如果Type
没有重载 operator=()
o = NULL; // error C2679: binary '=' : no operator found
// which takes a right-hand operand of type 'int'
// (or there is no acceptable conversion)
将其应用于 DirectX
当您使用 DirectX 时,您必须填写一些结构以将它们传递给 API 函数。这里是神奇之处。您可以ZeroMemory
将其设置为 0 值,这主要是默认值,然后只需填写所需的值,简化您的代码并防止您使用奇怪的值出错(如果您创建对象并且不会设置一些成员变量,它将包含垃圾值)。
在 C 和 C++ 中,“对象”不能设置为NULL
. 指向对象的指针可以设置为NULL
,这意味着指针本身指向空(“空对象”)。
这与将对象的内容设置为“所有位为零”不同,后者就是这样ZeroMemory()
做的。您通常只能对structs
可能反应非常糟糕的成熟 C++ 对象执行此操作。
ZeroMemory() 将内存设置为 0。也就是说,它将清除内存。同样将对象(指向对象的指针)设置为 NULL 意味着该对象的基地址被初始化为 0。
ZeroMemory
用于将较大的内存块设置为零。它不应该用于不是“POD”(普通旧数据)的对象,即如果您的对象具有构造函数或虚拟方法。
NULL
用于指示指针指向“无”。
从技术上讲,您将从ZeroMemory(pointer, sizeof(pointer));
as得到相同的结果pointer = NULL;
,但是 a) 第二个更清晰,并且 b) 执行后者的速度很可能一样快或更快。
就良好实践而言,id 建议您同时使用两者。
// Consider mystuff as being a pointer to an object.
ZeroMemory(mystuff); // Makes this part of memory to be clean
mystuff = NULL; // Makes this pointer point to null so you dont access a 0-memory section.
您可以在使用 DirectX API 时使用 malloc 分配内存,在这种情况下,调用ZeroMemory();
将无法按预期工作。对于您分配的内存,malloc();
您可能应该调用 to free();
。在处理指针时,我通常在释放它们后立即将它们设置为 NULL,idk 是否这是一个好习惯。
Zero memory
将部分内存设置为零,并且对于将大向量设置为零的更常见的对象使用它是有害的,并且它工作得很快,并且Null
当您希望指针指向任何内容并且它们的使用取决于您的程序指针或设置时,它更常见记忆值
NULL
将算术类型变量或(数据或函数)指针变量设置为等于 0。由于 C++11,仅针对指针,nullptr
执行相同的操作,并且出于相同的原因建议使用;这是正确的和惯用的。
但是ZeroMemory
将 a 的内容设置为struct
或class
等于 0 byte-per-byte。
ZeroMemory
(或)是第二个参数设置为RtlZeroMemory
的预处理器定义。memset
0
void* memset(void* dest, int ch, std::size_t count);
#define ZeroMemory(dest,count) memset((dest),0,(count))
你可以说ZeroMemory
是memset
ing to 0
。
例子:
D3D11_BUFFER_DESC indexBuffDesc;
ZeroMemory(&indexBuffDesc, sizeof(indexBuffDesc));
// or:
memset(&indexBuffDesc,0,sizeof(indexBuffDesc));
ZeroMemory
就像格式化驱动器(不是快速格式化)。
想NULL
/nullptr
就像擦除一个充满宝藏的坚固金库的门,因此您将永远无法进入它。鉴于,ZeroMemory
正在破坏强大的保险库的内容,使所有宝藏和里面的其他一切都无效;你可以访问它,但那里什么都没有。这就是我对他们的看法。