Auto 和 Void 的区别?

Difference between Auto and Void?

我正在阅读 C++ 入门书(第五版),我对正在阅读的书有疑问。它说:

The type void* is a special pointer type that can hold the address of any object. Like any other pointer, a void* pointer holds an address, but the type of the object at that address is unknown.

好吧,我明白了,但是……我对这个说法有很多矛盾。首先,你不能用auto吗?它不是和 void 做同样的事情吗?意思不是

void *somePtr;

auto *somePtr;

一样吗?

其次,它说附加地址的类型未知。不能用typeid获取类型吗?像这样:

int a = 5;
auto *somePtr = 5;
std::cout << typeid(*somePtr).name() << std::endl;

回答你的第一个问题,

void 和 auto 不一样。 When you declare a variable of auto, it means it takes the data types of the value assigned.

例如:

auto a = 5 // 'a' 是整数类型

auto a = 5.0 // 'a' 是 float 等类型,

取消引用时可以观察到实际差异。

以上说法"the actual difference can be observed while dereferencing"回答了你的第二个问题。

void* 不能延迟,而 auto* 可以延迟

auto 使用编译时 type inference:变量有一个明确的类型,这是它的正确类型,但是类型是从它的值推断出来的。在 auto 变量的整个生命周期中,编译器将确保根据其实际推断类型

使用它

void*确实可以保存任何对象的地址,但与auto相反,你必须在使用它之前显式地将void*指针转换为不同的类型。与 auto 不同,转换是显式的,与 auto 不同,编译器无法警告不当使用。

在自动变量的情况下,它将采用从中获取它的变量的数据类型。例如 自动对象 = class_obj。这里 class_obj 的数据类型变成了 obj 的数据类型。您无需明确记住并键入强制转换。如果 void * 你需要知道数据类型并明确地进行类型转换。

您是否通过编译器尝试 运行 您的示例?碰巧的是,

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 视为告诉编译器

Don't care about what p pointer points to, I'll handle it myself (at run-time).

auto * p = (expression) 告诉编译器

Please figure out for me (at compile-time) what (pointer) type (expression) evaluates to and make the type of p be accordingly.

事实上,auto *很少有用。您可以简单地写成 auto ,如果初始化表达式是指针类型,则 auto 也将被推导为指针。

从编译器的角度:

  • 在 C++11 中,auto 使用与 template argument deduction 相同的推理规则。它基本上告诉编译器:"Deduce the type from the initializer."
  • void * 告诉编译器:"Here is a pointer pointing to an object whose type cannot possibly be known at compile time."

对于 auto,实际类型是 在编译时推导出来的,因此编译器可以警告可能的误用。

对于void *,实际类型由程序员在代码中推断使用reinterpret_cast转换为已知指针类型,通常在点该段代码的执行。


从程序员的角度:

  • 嘿编译器我太懒惰或太笨拙,无法编写类型。我会 auto 它,让你解决剩下的问题。 (而且看起来比我要写的那个小。除了 int。)
  • 嘿编译器,你敢惹我 void *。我会在需要时自己(在代码中...)找出类型 at runtime
    • 对于运行时多态性很有用,因为同一个指针可用于指向上下文中需要的不同类型的对象。
    • 如果您正在编写基础 class 并且您的客户端需要存储由客户端定义的 用户定义类型 的对象,这也很有用。

所以 NO auto NOT 等同于 voidvoid 表示 没有 。事实上,您甚至不能声明 void 类型的变量。然而 void * 是一种 特殊类型的指针 可以 指向任何东西!auto * 是多余的,只需使用普通改为旧 auto

在你的例子中,

int a = 5;
auto *somePtr = 5;
std::cout << typeid(*somePtr).name(); << std::endl;

您将地址 5 分配给 somePtr,这是非法的。不用说 *somePtr 在这种情况下也是非法的。虽然 auto 可能被推断为 int,但这是您想要打印的内容。

使用现代 C++ 技术,您很少会看到 void *s 和 reinterpret_casts 或任何原始指针,除了在任何库实现内部的深处。