void 指针:C 和 C++ 之间的区别
Posted
技术标签:
【中文标题】void 指针:C 和 C++ 之间的区别【英文标题】:void pointers: difference between C and C++ 【发布时间】:2010-12-16 17:57:36 【问题描述】:我试图了解 C 和 C++ 在 void 指针方面的区别。以下是用 C 编译而不是 C++ 编译(所有编译都使用 gcc/g++ -ansi -pedantic -Wall 完成):
int* p = malloc(sizeof(int));
因为malloc
返回void*
,C++ 不允许将其分配给int*
,而C 允许这样做。
但是,这里:
void foo(void* vptr)
int main()
int* p = (int*) malloc(sizeof(int));
foo(p);
return 0;
C++ 和 C 都可以毫无问题地编译它。为什么?
K&R2 说:
任何指向对象的指针都可以是 无损失地转换为
void *
类型 的信息。如果结果是 转换回原来的指针 类型,原来的指针是 恢复了。
这很好地总结了 C 中关于 void*
转换的所有内容。C++ 标准规定了什么?
【问题讨论】:
GMan 正确解释了您收到错误的原因。也就是说,如果你正在编写 C++ 代码,你应该使用 new/new[] 和 delete/delete[] 而不是 malloc/calloc 和 free/free。 【参考方案1】:在 C 中,与void*
之间的指针转换始终是隐式的。
在 C++ 中,从 T*
到 void*
的转换是隐式的,但从 void*
到其他任何东西都需要强制转换。
【讨论】:
你能提供你的第二个声明的来源吗?它是用 C++ 标准编写的吗? 真的没什么好引用的。它在第 4.10.2 节中。它几乎说T*
可以转换为void*
。它省略了反面,暗示你必须使用演员表。
@zaharpopov:查找 reinterpret_cast 或 static_cast
@GMan:明确不说明从 void* 转换意味着不可能做到这一点(即不允许(隐式)从 void* 转换为任何其他指针类型)。然后通过查看强制转换运算符的定义,您可以了解这些运算符可以对对象做什么。他们对将 void* 转换为其他类型的定义非常清楚。
@GMan:如果“在 C 中,指针转换总是隐式的”你的意思是与void *
之间的转换,那么你是对的。否则,在指针转换方面,C 与 C++ 一样严格。例如,在 C 中没有从 char *
到 int *
的隐式转换。从历史上看,习惯上在 C 编译器中将指针转换错误报告为“警告”,这导致了一个关于 C 据称允许所有和任何隐式指针转换。然而,这只是一个神话。【参考方案2】:
C++ 的类型比 C 更强。许多转换,特别是那些暗示对值的不同解释的转换,都需要显式转换。 C++ 中的 new 运算符是一种类型安全的在堆上分配内存的方法,无需显式强制转换。
【讨论】:
【参考方案3】:了解指针类型转换实际上并不需要执行额外的 CPU 指令是很有用的。在编译期间对它们进行分析,以了解开发人员的意图。 void *
是一个不透明的指针。它只是说指向对象的类型是未知的。 C 是弱类型的。它允许在 (void *
) 和任何 (T*
) 之间隐式进行直接转换。 C++ 是强类型的。从 (void *
) 到 (T*
) 的转换对于强类型语言来说并不是很好的例子。但是 C++ 必须保持与 C 的向后兼容,因此它必须允许这样的转换。指导原则是:显式优于隐式。因此,如果您希望将 (void*
) 转换为某个特定的 (T*
) 指针,则需要在代码中显式编写。从 (T*
) 到 (void*
) 的转换不需要显式转换,因为直接对 (void*) 指针无能为力(尽管可以调用 free())。因此 (T*
) 到 (void*
) 的转换非常安全。
【讨论】:
指针转换是否需要 CPU 指令是一个实现细节。在 C 和 C++ 语言中,绝对没有任何东西需要这种转换纯粹是概念性的(即不需要 CPU 指令)。相反,这两种语言都是专门制定的,以允许对不同的指针类型进行不同的表示。虽然“理解”在典型情况下,转换实际上在 CPU 级别上没有任何作用可能确实有用,但编写依赖于该假设的 C 或 C++ 代码是一个严重的错误。 ...而且我不明白“保持向后兼容”的意义。 C++ 需要显式转换才能从void *
转换。那已经不向后兼容 C。
C++ 并不完全向后兼容 C。它只是提供了在必要时尽可能简化迁移的方法。从弱类型转换到强类型自然会导致兼容性问题。 C++ 只是尝试提供简单的方法(例如对 void 指针进行显式类型转换)来简化迁移。
@AndreyT:为了再次强调你的观点,派生类和基类之间的转换(尤其是多重继承)可能需要 CPU 才能将指针移动到内存中对象的适当部分.
C++ 遭受与 C 相同的隐式类型提升规则这一事实使得 C++ 也是一种非常弱类型的语言。除了 void 指针之外,“强类型”还有更多内容。以上是关于void 指针:C 和 C++ 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章