2012-08-08 128 views
3

在C中,void指针被隐式地转换为另一种类型。C与C++中void *的转换

请参见下面的程序:

int main() 
{ 
    void *p; 
    int* ptr,i=5; 
    p=&i; 
    ptr=p; <--------------------------- 
    return 0; 
} 

当C环境下运行的程序compiles successfully

但是,如果在同一个程序为C下运行++环境下,我得到了下面error

prog.cpp: In function ‘int main()’: 
prog.cpp:8: error: invalid conversion from ‘void*’ to ‘int*’ 

这意味着,在C++中,我们需要明确的典型案例一void指针。

那么,为什么new运算符的返回类型是void *?如何将其转换为所需的类型?

+0

我认为你可以指示C编译器对于隐式强制转换更迂腐。 – maba 2012-08-08 13:25:37

回答

3

如果您超载operator new,那么确实会返回void*。超载operator new基本上是像C.

malloc()一个简单的分配功能但当你使用操作new,你正在做的不仅仅是调用该函数更多;例如,你也隐式地调用构造函数。返回确切的正确类型是与new构建和超载operator new函数之间的另一个隐含差异。

C++给你一个错误,因为void*可能指向任何东西。所以如果你试图将它分配给某个具体的东西,那么你正在做出一个可能并非如此的假设。由于C++是强类型的,所以你必须告诉编译器你的假设并明确表示它;这是类型安全提供的保护机制。 C不是强类型的,完全由开发人员负责照顾。

+0

+1是的 - 非常同意。应该添加C++是强类型的。 C不是。 – 2012-08-08 13:19:53

1

new运算符由编译器专门处理,它从参数中获取类型为new,并将隐式类型转换为正确的类型。

如果您创建了自己的operator new,则必须返回void指针,因为实际上您不知道类型,只需分配内存量即可。

1

因为new不是函数,所以它是一个运算符,并且由编译器专门处理。

1

C++对指针强制转换施加更严格的规则。其中一个原因可能是因为C++中的指针最终可能会导致机器码,即它不是一个纯粹的化妆品。

例如,类A继承BC(按此顺序)。如果您将指针指向C并将其转换为A - 此结果为(原始)指针移位。

-1

http://www.cplusplus.com/reference/std/new/operator%20new/

运营商新的可以明确地被称为一个普通的功能,但在 C++,新是一个非常具体的行为操作:使用new运算符的表达式 ,首先调用函数operator新其类型说明符的大小为 作为第一个参数,如果成功,则 会自动初始化或构造对象(如果需要)。 最后,表达式将作为指向适当的 类型的指针进行评估。

注意最后一句。

1

您需要输入:

ptr = (int *) p; 

的新的结果不是一个void *。这取决于你正在创建的对象。 如果你这样做

ptr = new int [2]; 

有没有重铸涉及。

+0

这里的reinterpret_cast (p)优于C风格演员。 C++提供了不同的转换操作符,应该使用它们。 – Thelvyn 2012-08-08 13:25:21

+0

避免使用'reinterpret_cast' - 在这种情况下'static_cast'不仅够用,而且也是可取/推荐的。 – 2012-08-08 13:48:28

0

那么,为什么新操作符的返回类型是void *?

您的意思是关键字new,用于像int * p = new int[42];这样的新表达式中吗?该表达式具有正确的类型,在此情况下为int*,因此不需要转换。您是指内存分配功能operator new()?像malloc(),这是处理原始内存,而不是类型的对象,所以它的返回类型是一个非类型化的void*。它在内部由一个新表达式使用,该表达式知道正在创建的对象的类型,所以一旦对象被完全构建,就可以执行必要的指针转换。

在极少数情况下,如果您想在自己的代码中使用它,您必须自己将其转换为正确的类型;但你几乎总是通过新表达式间接使用它,而不必担心这些细节。