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 等同于 void
。 void
表示 没有 。事实上,您甚至不能声明 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_cast
s 或任何原始指针,除了在任何库实现内部的深处。
我正在阅读 C++ 入门书(第五版),我对正在阅读的书有疑问。它说:
The type
void*
is a special pointer type that can hold the address of any object. Like any other pointer, avoid*
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 ofp
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 等同于 void
。 void
表示 没有 。事实上,您甚至不能声明 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_cast
s 或任何原始指针,除了在任何库实现内部的深处。