为什么我可以使用 static_cast With void* 而不是 With char*
Why can I use static_cast With void* but not With char*
我知道 reinterpret_cast
主要用于往返 char*
。
但我惊讶地发现 static_cast
可以用 void*
做同样的事情。例如:
auto foo "hello world"s;
auto temp = static_cast<void*>(&foo);
auto bar = static_cast<string*>(temp);
我们使用 reinterpret_cast
和 char*
而不是 static_cast
和 void*
有什么好处?与严格的别名问题有关吗?
一般来说,static_cast
会强制转换任何两种类型,只要其中一种类型可以隐式 转换为另一种类型。这包括算术转换、向下转换、向上转换以及与 void*
.
之间的转换
也就是说,如果此转换有效:
void foo(A a);
B b;
foo(b);
那么static_cast<B>(a)
和static_cast<A>(b)
也都有效
由于任何指针都可以隐式转换为 void*
,因此您的行为很奇怪。
reinterpret_cast
通过重新解释值的位模式来进行转换。正如您在问题中所说,通常是为了在不相关的指针类型之间进行转换。
是的,您可以通过 void*
在不相关的指针类型之间进行转换,方法是使用两个 static_cast
:
B *b;
A *a1 = static_cast<A*>(b); //compiler error
A *a2 = static_cast<A*>(static_cast<void*>(b)); //it works (evil laugh)!
但这是在违反规则。如果您真的需要这个,请使用 reinterpret_cast
。
你的问题确实有两部分:
- 我应该使用
static_cast
还是 reinterpret_cast
来处理指向对象底层位模式的指针而不关心对象类型?
- 如果我应该使用
reinterpret_cast
是 void*
还是 char*
更适合解决这个底层位模式?
static_cast
: Converts between types using a combination of implicit and user-defined conversions
在5.2.9[expr.static.cast]13标准中,其实给出了例子:
T* p1 = new T;
const T* p2 = static_cast<const T*>(static_cast<void*>(p1));
它利用隐式转换:
A prvalue pointer to any (optionally cv-qualified) object type T
can be converted to a prvalue pointer to (identically cv-qualified) void
. The resulting pointer represents the same location in memory as the original pointer value. If the original pointer is a null pointer value, the result is a null pointer value of the destination type.*
然而,没有从类型 T
的指针到 char*
的隐式转换。因此,完成该转换的唯一方法是使用 reinterpret_cast
.
reinterpret_cast
: Converts between types by reinterpreting the underlying bit pattern
因此,在回答问题的 1 部分时,当您转换为 void*
或 char*
时,您希望使用底层位模式,应该使用 reinterpret_cast
,因为它的使用表示 reader 转换 to/from 底层位模式。
接下来让我们比较一下 void*
和 char*
。这两者之间的决定可能更多地取决于应用程序。如果您打算将标准库函数与底层位模式一起使用,只需使用该函数接受的类型:
值得注意的是,特定于 C++ 的库更喜欢 char*
来指向内存。
作为 void*
保留内存似乎出于兼容性原因被保留为指针 here。因此,如果 cstring
库函数不会在您的基础位模式上使用,请使用 C++ 特定库行为来回答您问题的 2 部分:更喜欢 char*
而不是 void*
.
我知道 reinterpret_cast
主要用于往返 char*
。
但我惊讶地发现 static_cast
可以用 void*
做同样的事情。例如:
auto foo "hello world"s;
auto temp = static_cast<void*>(&foo);
auto bar = static_cast<string*>(temp);
我们使用 reinterpret_cast
和 char*
而不是 static_cast
和 void*
有什么好处?与严格的别名问题有关吗?
一般来说,static_cast
会强制转换任何两种类型,只要其中一种类型可以隐式 转换为另一种类型。这包括算术转换、向下转换、向上转换以及与 void*
.
也就是说,如果此转换有效:
void foo(A a);
B b;
foo(b);
那么static_cast<B>(a)
和static_cast<A>(b)
也都有效
由于任何指针都可以隐式转换为 void*
,因此您的行为很奇怪。
reinterpret_cast
通过重新解释值的位模式来进行转换。正如您在问题中所说,通常是为了在不相关的指针类型之间进行转换。
是的,您可以通过 void*
在不相关的指针类型之间进行转换,方法是使用两个 static_cast
:
B *b;
A *a1 = static_cast<A*>(b); //compiler error
A *a2 = static_cast<A*>(static_cast<void*>(b)); //it works (evil laugh)!
但这是在违反规则。如果您真的需要这个,请使用 reinterpret_cast
。
你的问题确实有两部分:
- 我应该使用
static_cast
还是reinterpret_cast
来处理指向对象底层位模式的指针而不关心对象类型? - 如果我应该使用
reinterpret_cast
是void*
还是char*
更适合解决这个底层位模式?
static_cast
: Converts between types using a combination of implicit and user-defined conversions
在5.2.9[expr.static.cast]13标准中,其实给出了例子:
T* p1 = new T;
const T* p2 = static_cast<const T*>(static_cast<void*>(p1));
它利用隐式转换:
A prvalue pointer to any (optionally cv-qualified) object type
T
can be converted to a prvalue pointer to (identically cv-qualified)void
. The resulting pointer represents the same location in memory as the original pointer value. If the original pointer is a null pointer value, the result is a null pointer value of the destination type.*
然而,没有从类型 T
的指针到 char*
的隐式转换。因此,完成该转换的唯一方法是使用 reinterpret_cast
.
reinterpret_cast
: Converts between types by reinterpreting the underlying bit pattern
因此,在回答问题的 1 部分时,当您转换为 void*
或 char*
时,您希望使用底层位模式,应该使用 reinterpret_cast
,因为它的使用表示 reader 转换 to/from 底层位模式。
接下来让我们比较一下 void*
和 char*
。这两者之间的决定可能更多地取决于应用程序。如果您打算将标准库函数与底层位模式一起使用,只需使用该函数接受的类型:
值得注意的是,特定于 C++ 的库更喜欢 char*
来指向内存。
作为 void*
保留内存似乎出于兼容性原因被保留为指针 here。因此,如果 cstring
库函数不会在您的基础位模式上使用,请使用 C++ 特定库行为来回答您问题的 2 部分:更喜欢 char*
而不是 void*
.