我正在阅读C ++入门书(第五版),我对正在阅读的书有疑问。它说:
类型
final
是一种特殊的指针类型,可以保存地址 任何对象。像任何其他指针一样,final
指针保存一个地址, 但该地址的对象类型未知。
好的,所以我明白了,但......我的声明有很多矛盾。首先,你不能使用void*
吗?它不像void*
那样做吗?含义不是
auto
和
void
同样的?
其次,它说附加地址的类型是未知的。你不能用void *somePtr;
来获取类型吗?像这样:
auto *somePtr;
答案 0 :(得分:11)
您是否尝试通过编译器运行示例?碰巧,没有
auto * p; // error
,也不
int a = 0;
void * p = &a;
std::cout << typeid(*p) << '\n'; // error
将同时编译
void * p;
和
int a = 0;
auto * p = &a;
std::cout << typeid(*p) << '\n';
很好。
为void *
和auto *
提供一个非正式且易于记忆的类比,请将void * p
视为告诉编译器
不关心
p
指针指向的内容,我会自己处理它(在运行时)。
而auto * p = (expression)
告诉编译器
请为我(在编译时)确定({指针]类型
(expression)
评估的内容,并相应地设置p
的类型。
事实上,auto *
很少有用。您可以简单地编写auto
,如果初始化表达式是指针类型,auto
也将被推断为指针。
答案 1 :(得分:9)
auto
使用编译时type inference:变量有一个确定的类型,它是正确的类型,但是从它的值推断出类型。在auto
变量的整个生命周期中,编译器将确保根据其实际推断类型使用它
void*
确实可以保存任何对象的地址,但与auto
相反,您必须在使用它之前将void*
指针显式转换为其他类型。与auto
不同,转换是显式的,与auto
不同,编译器无法警告不正确的使用。
答案 2 :(得分:2)
从编译器的角度来看:
auto
使用与template argument deduction相同的推理规则。它基本上告诉编译器:“从初始化器中删除类型。” void *
告诉编译器:“这是一个指向一个对象的指针,该对象的类型在编译时是不可能知道的。” 对于auto
,实际类型是在编译时推导,因此编译器可以警告可能的误用。
对于void *
,程序员使用reinterpret_cast
在代码中推导出实际类型,以强制转换为已知指针类型,通常是在该段的执行点代码。
从程序员的角度来看:
auto
它让你弄明白其余的。 (它看起来比我要写的类型要小。除了 int
。) void *
。当我需要时,我会在运行时中找出类型(在代码中...)。
所以否 auto
NOT 等同于void
。 void
表示 nothing 。实际上,您甚至无法声明void
类型的变量。 void *
但是特殊类型的指针可以指向任何内容!并且auto *
是多余的,只需使用普通的auto
代替。
在您的示例中,
int a = 5; auto *somePtr = 5; std::cout << typeid(*somePtr).name(); << std::endl;
您已将地址5
分配给somePtr
,这是非法的。毫无疑问地说*somePtr
在这种情况下也是非法的。虽然auto
可能推导为int
,但这是您要打印的内容。
使用现代C ++技术,除了深入任何库实现内部之外,您很少看到void *
和reinterpret_cast
或任何原始指针。
答案 3 :(得分:1)
回答你的第一个问题,
void和auto不一样。 sizeof(allDivisions[0].quarterlySales[0])
。
代表:
自动a = 5 //&#39; a&#39;是整数
自动a = 5.0 //&#39; a&#39;是float等类型,
解除引用时可以观察到实际差异。
以上陈述&#34;在解除引用时可以观察到实际差异&#34;回答你的第二个问题。
void *不能被引用,而auto *可以是deferenced
答案 4 :(得分:0)
如果是自动变量,它将采用变量的数据类型。例如 Auto obj = class_obj。这里class_obj的数据类型变为obj的数据类型。你不需要明确记住并输入强制转换。如果是void *,你需要知道数据类型并明确地输入类型。