自动推导基础
auto
关键字的推导过程完全处于 compile-time,所以并不会影响程序性能。应该放心大胆的使用。
cpp
auto i = 1; // i will become int auto l = 1LL; // l will become long long auto d = 1.0; // d will become double auto f = 1.0f; // f will become float std::vector<int> ivec{1, 2, 3, 4, 5}; for (auto i : ivec) std::cout << i << " "; // 1 2 3 4 5
这样使用 auto
可能会要求你记住一些字面量的类型标识:
- 前置
标识 含义 类型 u Unicode 16 character char16_t
U Unicode 32 character char32_t
L wide character wchar_t
u8 utf-8(string literals only) char
可能经常用 VS 和 Windows API 的人比较熟悉 L
,用来标识宽字符。(不得不说,这一点,微软还是挺超前的)
- 后置
字面量 标识 类型 整型 u / U
unsigned
整型 l / L
long
整型 ll / LL
long long
浮点 f / F
float
浮点 l / L
long double
这些与 C 语言一脉相承,应该比较熟悉了。
特殊情况
cpp
auto str = "hello";
请问,str
是什么类型?最近才发现,很多初学者竟然想当然的认为str
是std::string
.(尤其是没有 C 语言基础的)
实际上,str
此时是 const char *
.
所以当你对 str
进行 range for 的时候,就会傻眼。
cpp
for (auto c : str) { // error! str 没有 begin() 和 end() //... }
上述情况应该如何避免?
cpp
auto& str = "hello";
请问,str
是什么类型?
是 const char[6]
. 这是一个数组了,那么 range for 当然没问题了。
还有别的方法吗?
当然,右值引用不是吃闲饭的:
cpp
auto&& str = "hello";
range for 照样没问题。请问 str
此刻是什么类型?
是 const char(&)[6]
.
这都是非常基础的内容,你都清楚吗?
另外补充一个:
cpp
auto il = {1, 2, 3, 4, 5, 6};
不要觉得 il
会是 std::array
或 普通数组,甚至是 std::vector
. 它的类型应该是: std::initializer_list
。
什么时候该用 auto
- 一种说法是:能用
auto
的地方都该用。(尤其是受到python
等动态语言影响的人)。 - 另一种说法:
auto
会让代码变得不直观,在一个强类型的语言中,会搞得人莫名其妙。
经过一段时间的疯狂实践。我觉得上述两种观点都有失偏颇。
其实,开始我是支持第一种观点的,于是开始大量使用 auto
, 直到有一天 review 自己的代码时。竟然发现很多变量完全看不出是什么类型。如:
cpp
auto foo = bla(); // 请问 foo 你能看出类型来吗?
这就傻眼了。违反了最基本的程序设计原则——“清晰易懂,方便扩展”,看都看迷糊了,扩展毛啊。
但有些情况,其实极大程度上的简化了程序,使之简洁明了:
cpp
auto foo = std::make_shared<Foo>(); // 一看就知道类型 for (auto iter = vec.cbegin(); iter != vec.cend(); ++iter) {} // 一看就知道类型
上述两种情况下,把 auto
扩展开来,会显得重复、冗长。
这两个例子,应该能够说明使用 auto
的那条 “金线” 在哪了。我们的目的不是为了用而用,而是尽可能的让自己的程序,易于维护,保持新鲜。
故,不要滥用,不要避讳。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。