为什么我们不能隐式地从void *赋值给C ++中的任何其他类型,但它在C中是首选?
根据这个
最好不要在C中 强制转换malloc ,因为如果转换malloc ,则会隐藏将被标记的错误,导致很难找到错误。 此外,在维护期间,如果指针的类型发生变化但铸件没有改变,则再次发现很难找到错误。 最有经验的程序员选择的方法是:
p = malloc ( n * sizeof *p );
malloc没有强制转换,因为不需要一个,而不是使用sizeof(type)来确定块的大小,而是使用sizeof * ptr 。 通过解除引用指针并获取其大小,可以给出正确的值,而不必担心如果指针的类型改变则修改分配请求。
但它不会在C ++中编译。 为什么?
这意味着如果malloc的返回被转换,那么将被标记的错误被隐藏?
它不会在C ++中编译。 为什么?
因为C和C ++是不同的语言。
C标准允许void *
和其他指针类型之间的隐式转换。 它们不被C ++标准所允许。 在C中,演员阵容是不必要的,并且没有基本的编程指南“不要重复自己”,而在C ++中,语言需要演员表(这不是偏好问题)。
这意味着如果
malloc
的返回被转换,那么将被标记的错误被隐藏?
隐式函数声明不再是C语言的一部分,但许多编译器继续支持它作为与旧代码库兼容的扩展。 如果C函数没有原型,则假定返回int
。 如果你无意中将#include
从代码中删除但是调用malloc
,编译器可能会认为它返回int
而不是void *
[1]。 使用显式强制转换,假定的int
结果将转换为void *
,这通常可能导致无效指针。 这很糟糕,可能导致难以诊断的运行时故障。
另一方面,如果您没有显式强制转换,则在编译时会收到警告或错误,指向错误的确切来源,这更容易诊断和修复。[2]
-
实际上,与使用返回指针(或其他类型)的函数相比,
malloc
不是问题,因为许多编译器都知道malloc
并专门处理它。 -
在实践中,一些现代编译器实际上会警告你是否有演员表,但是肯定仍在使用的编译器如果演员阵容存在则不会发出警告,从而导致合理的偏执和防守编程。
但它不会在C ++中编译。 为什么?
在使用void*
作为通用指针的便利性和防止无效类型转换的安全性之间进行权衡。
在C中, void*
被广泛使用,因为它是编写通用代码的唯一合理方式; 因此,在该语言中,为方便起见,它可以隐式转换为另一种指针类型。
在C ++中,有类型安全的编写通用代码的方法,因此很少使用void*
; 特别是,你使用type-safe new
来分配和初始化一个对象,而不是malloc
来分配原始内存并假装它包含一个对象。 因此,在该语言中,禁止从void*
隐式转换以提供更强的类型安全性。
这意味着如果
malloc
的返回被转换,那么将被标记的错误被隐藏?
线索在上一句话中:
除非在未包含声明
malloc
的标头stdlib.h
,否则没有任何问题
在(较旧的方言)C中,你可以调用一个尚未声明的函数; 隐式声明一个返回类型为int
的函数。 因此,如果您在不包含标头的情况下调用malloc
,则会得到错误地认为它返回int
。 如果没有强制转换,当您尝试将其分配给指针时,会出现编译器错误。 使用强制转换,代码将被编译,可能会产生模糊的运行时错误和冗长的调试会话。
在C ++(和现代C)中,所有函数必须在使用前声明,因此即使您出于某种原因使用了malloc
,也不会发生此错误。
它在C ++语言中是不允许的,因为C ++具有类型安全性
它与类型安全有关。 特别是C允许从void*
到其他类型的隐式转换,但c ++没有,这就是它在C中编译而不是C ++的原因。 这是C和C ++不同的方式之一。 C不是C ++的子集。
在c ++中,你应该使用new
而不是malloc
。 New做了类型安全分配来解决这个问题。