如果我可以保证使用正确的类型来分配内存,使用 reinterpret_cast 是否安全?
Is it safe to use a reinterpret_cast if I can guarantee the correct type was used to allocate the memory?
我正在尝试使我的 C++ 代码跨平台。在 Windows 上,我使用 Windows.h 头文件,在 macOS 和 Linux 上,我使用 unistd.h 头文件。
如果 OS 是采用 char* 类型的 windows,我将调用一个函数。 mac 和 linux 的等效调用采用 char**。我目前有一个采用 void* 类型的函数,因此我可以为这两种情况使用 1 个函数。然后我检查操作系统和 reinterpret_cast 到正确的类型。
void DoSomething(void* thing) {
#if defined(__APPLE__) || defined(__linux__)
// Init thing as char**
thing = new char*[...];
thing[0] = new char[...];
.
.
.
UnixFunction(reinterpret_cast<char**>(thing));
#elif defined(_WIN32)
// Init thing as char*
thing = new char[...];
WindowsFunction(reinterpret_cast<char*>(thing));
#endif
}
int main() {
void* thing;
DoSomething(thing);
return 0;
}
不管我是否应该这样做,这安全还是未定义的行为?
听起来你问的是安全的。但是,您的代码看起来有点不对劲:
void DoSomething(void* thing) {
thing = new char*[...];
这将使调用者无法访问分配的内存,因为 thing
是调用者传入的地址,但随后您立即覆盖了该地址,因此您无法将调用者给了你,and/or调用者无法知道你分配了什么内存。
例如,您可以采用 (void*& thing)
以便您对指针所做的更改对调用者可见。或者只是 return 来自函数的指针。
如果您修复了该设计错误,reinterpret_cast
本身就不会成为问题。你甚至可以将指针指向 uintptr_t
或 intptr_t
,然后使用 reinterpret_cast
再次返回,如果你想要一种方法来传递地址而无需知道类型,直到你再次使用它们。
我正在尝试使我的 C++ 代码跨平台。在 Windows 上,我使用 Windows.h 头文件,在 macOS 和 Linux 上,我使用 unistd.h 头文件。
如果 OS 是采用 char* 类型的 windows,我将调用一个函数。 mac 和 linux 的等效调用采用 char**。我目前有一个采用 void* 类型的函数,因此我可以为这两种情况使用 1 个函数。然后我检查操作系统和 reinterpret_cast 到正确的类型。
void DoSomething(void* thing) {
#if defined(__APPLE__) || defined(__linux__)
// Init thing as char**
thing = new char*[...];
thing[0] = new char[...];
.
.
.
UnixFunction(reinterpret_cast<char**>(thing));
#elif defined(_WIN32)
// Init thing as char*
thing = new char[...];
WindowsFunction(reinterpret_cast<char*>(thing));
#endif
}
int main() {
void* thing;
DoSomething(thing);
return 0;
}
不管我是否应该这样做,这安全还是未定义的行为?
听起来你问的是安全的。但是,您的代码看起来有点不对劲:
void DoSomething(void* thing) {
thing = new char*[...];
这将使调用者无法访问分配的内存,因为 thing
是调用者传入的地址,但随后您立即覆盖了该地址,因此您无法将调用者给了你,and/or调用者无法知道你分配了什么内存。
例如,您可以采用 (void*& thing)
以便您对指针所做的更改对调用者可见。或者只是 return 来自函数的指针。
如果您修复了该设计错误,reinterpret_cast
本身就不会成为问题。你甚至可以将指针指向 uintptr_t
或 intptr_t
,然后使用 reinterpret_cast
再次返回,如果你想要一种方法来传递地址而无需知道类型,直到你再次使用它们。