根据这个网站:
您不能从void*隐式分配任何其他类型。例如,以下代码在C语言中是完全有效的(事实上,可以说这是在C语言中执行此操作的首选方法)
int *x = malloc(sizeof(int) * 10);
但它不会在C ++中编译。
Bjarne Stroustrup本人的解释是这不是类型安全的。这意味着您可以有一个void*指向所有内容,然后,如果您将存储在void *中的地址分配给另一个不同类型的指针,则根本没有任何警告。
考虑以下:
int an_int;
void *void_pointer = &an_int;
double *double_ptr = void_pointer;
*double_ptr = 5;
cout<
为*double_ptr赋值5时,它将写入8个字节的内存,但整数变量an_int仅为4个字节。因此,当您打印an_int变量的值时,输出将为0,因为根据4个字节,编译器选择5(5.000 ..)的最低有效位为0。
在C ++中,强制从void指针进行强制转换会使程序员注意这些事情。因此,在该语言中,禁止从void *进行类型转换以提供更强的类型安全性。
但是在此示例中将void *转换为double *时,我确实感到困惑:
int an_int;
void *void_pointer = &an_int;
double *double_ptr = (double *)void_pointer;
*double_ptr = 5;
cout<
输出将保持为0。
那么,类型安全扮演什么角色呢? Bjarne Stroustrup对类型安全的确切解释是什么?
...而在c语言中您不必询问,而在c ++语言中,您现在不得不问=>更多类型安全
但是在示例中我给类型转换起什么作用呢? 那么什么时候类型转换有用呢?
"类型安全"表示除非您明确要求这样做,否则编译器将不允许您对操作使用不匹配的类型(例如,在执行c样式或c ++ reinterpret_cast<>类型强制转换时)在您的样本中)。
但是在示例中我给类型转换起什么作用呢?那么什么时候类型转换有用呢?
@VikasVerma:当您使用一种类型(char)而想要另一种(int)时。或者您有一个char*,而您想要一个std::string。
@VikasVerma从int*到double*的类型转换无效,因为它们的指向值的二进制表示形式完全不同!
@π?ντα?ε?类型强制转换也是类型安全的,您的语句doing a type cast of ANY kind是错误的
@Paranaix更好吗?
是的:如果您看下面我提供的示例,它告诉您"编译器不会让您使用不匹配的类型进行操作..."完全没有帮助。
@IngoBlackman关键是C ++根本不是类型安全的。我对此表示怀疑!如果发现某些情况,则有责任破坏类型安全并要求进行未定义的行为。除了简单地显示未定义的行为内容之外,您还可以使用错误类型的强制转换原始指针来详细说明并显示更多证据吗?
强大的静态类型安全性是C ++的核心元素。基本上,这意味着您只能在兼容类型之间传输信息,并且任何类型中最兼容的类型就是该类型。通过使用具有相同类层次结构的派生类型的基本类型等方法来加强这种想法,以此类推,从而大大提高了复杂性和逻辑强度。还有一个核心思想是C ++尽可能与C保持兼容。一个失败的结果是void *与任何指针类型都兼容。不过,通常最好避免这样做,因为C ++中总是有更好的设计。
我无法抗拒。"类型安全"是C ++的营销手段。考虑以下代码:
#include
class A {
public:
int x;
};
class B : public A {
// B is derived from A, which makes
// B"compatible" to A
public:
// B adds a 2nd member, which means
// that B is"bigger" than A
int y;
};
int main()
{
B a1[10];
A *a2;
a2 = a1; // this is legal :-(
a1[0].x=1;
a1[0].y=1;
a2[0].x=2;
a2[1].x=3; // Upps: this probably overwrites a1[0].y
printf("a1[0].x = %d
",a1[0].x);
printf("a1[0].y = %d
",a1[0].y);
return 0;
}
使用" g ++ -Wall -pedantic -fstrict-aliasing"或其他找到的选项进行编译。我至少没有设法发出警告。上面的代码不使用任何类型强制转换,但您仍然会得到中断的代码,或者至少可以肯定地说,它并没有按照您的预期做。
现在,C ++专家可能建议使用"向量"或其他方式。但这不是重点。关键是C ++根本不是类型安全的。
编辑:
由于这似乎令人困惑,因此以下是问题根源的解释。
因为C ++是面向对象的,所以"类B"与"类A"兼容(因为"类B"是从"类A"派生的)。因此,这意味着您可以在需要" A类"对象的地方使用" B类"对象。这又意味着您可以在需要" A *类"指针的地方使用" B *类"指针。
现在的问题是C ++允许指针算术(因为它是C遗留的)。指针算法与继承和兼容类型的交互非常差。因为在上面的示例中," a2 + 1"(a2是" class A *"指针)导致了与" a1 + 1"(a1是" class B *"指针)不同的地址。
综上所述:C ++认为类型" B *"与类型" A *"兼容,但不幸的是,当您将它们用于指针运算时,这些类型不兼容。
那都是完全错误的! @IngoBlackman关键是C ++根本不是类型安全的。我对此表示怀疑!如果发现某些情况,则有责任破坏类型安全并要求进行未定义的行为。除了简单地显示未定义的行为内容之外,您还可以使用错误类型的强制转换原始指针来详细说明并显示更多证据吗?
顺便说一句,体面的编译器能够针对您传递的参数类型检测不匹配的printf()格式说明符,并为此至少警告您!
您在这里提到的问题可能是切片,但是那仍然在用户正确处理的范围内,编译器无法知道您是这样滥用c ++的。
您能否在上面的示例中告诉我,哪里有"类型严重错误的强制转换原始指针"?没有类型转换。为什么提到" printf"?那只是为了输出值。问题是在printfs上方。
问题是在printfs上方。看到了,提到切片...
@π?ντα?ε? :是的,我所指的问题也称为"切片"。"编译器无法知道您这样滥用c ++"。所以编译器不知道吗?我认为这是一种" TYPE SAFE"语言。那么为什么编译器不知道? (没有类型会强制执行任何操作,为什么?)
@π?ντα?ε? :因此,如果您注意到它有关切片的信息,为什么还要提及" printf"?
类型安全性意味着您无法做到这一点,而不会期待未定义的行为!
让我们继续聊天中的讨论
因此,如果您注意到其有关切片的信息,为什么还要提到" printf"呢?
总结(从聊天中):复制arent引用与c ++中的原始实例相同的实例,因为它们很可能在Java或c#中处理。那并不会使c +成为类型安全语言!
我同意这是C ++中使它成为危险语言的众多陷阱之一。但是,规则是:(1)您可以获取A数组的第一个元素的地址,并对该指针进行指针算术以获取该数组的后续元素,(2)您可以将指针转换为< x9>指向A的指针。那就是您可以合法地做的一切;您不能合法地做您正在做的事情,即对指向B s数组的A指针进行指针算术运算。这在C ++中根本不是合法的事情,您必须知道这一点,而不要这样做。
@eric:您如何定义"合法"?编译器甚至无法发出警告。我认为允许这种构造的语言只是糟糕的语言设计,而且肯定不是"类型安全的"。