百科问答小站 logo
百科问答小站 font logo



如何评价 C++ 11 auto 关键字? 第1页

  

user avatar   lan-se-52-30 网友的相关建议: 
      

auto很好,即使可能有些缺点,也是瑕不掩瑜。

对于auto而言,其在于type deduce,那么第一点,它不会允许没有初始化值的声明,如:

       int x;  auto y; // error      

这是很好的,有些开发者总是会直接用一些没有初始化的变量,然后后面运行结果不对。而运行的错误找起来总是比编译的难许多。

auto可以节省很多字,尤其是容器的iterator,这也是经常举的例子

       vector<int> v;  vector<int>::iterator iter = v.begin(); // #1  auto I = v.begin(); // #2       

你是喜欢 #1 还是 #2这样的写法呢?

auto配合lambda使用很好。对于lambda来说,其是一个callable object,每一个类型都是独一无二的,这个类型只有编译器知道,于是你可以:

       auto closure = [](const int&, const int&) {}      

当然,你也可以使用std::function来存储,然而这远远没有auto来的优雅。

与此同时,在C++14中,泛型lambda也允许了参数类型可以为auto类型,如

       auto closure = [](auto x, auto y) { return x * y;}     

auto配合decltype,可以解决一些以前可能需要很丑的解法

       template<class T, class U> ? ? ? mul(T x, U y)  {      return x*y;  }      

由于x, y是在参数,返回的是 x * y的类型,于是,要得到x * y的类型怎么办?当然可以利用decltype来取,但是你需要取的是 x * y的,而x,y却在参数后面,于是那就转为万能的0,在转为指针,再取指针。

       template<class T, class U> decltype(*(T*)(0)  *  *(U*)(0)) mul(T x, U y)  {      return x*y; }      

那么用auto占位置即可:

       template<class T, class U> auto mul(T x, U y) -> decltype(x * y)  {      return x*y; }      


Thanks to C++14, auto在C++14可以作为函数返回类型了,于是你可以直接这样了

       template<class T, class U> auto mul(T x, U y) {      return x*y; }      

说完这么多好处,那么来说说auto可能引起的问题。

其中第一条可能就是很多人所说的可能会降低代码的可读性。然而对于这一条,我持中立态度。若有IDE,我认为这不会是问题,但是若你认为使用强制的类型声明可以让代码更可读,也可以继续使用,C++的哲学也是相信程序员,不会束缚你做什么任何事情。

然后第二条就是auto可能得不到你预想的类型,如vector<bool>[]的返回类型。

       #include <iostream> #include <vector> #include <typeinfo> using namespace std; int main() {     vector<bool> v;     v.push_back(true);     auto var = v[0];     cout << typeid(var).name() << endl; }      

vector<bool>是一个奇葩的存在,它的[]返回的不是bool,是一个表示单独bool引用的proxy class,于是你得到是这个引用(而你平常使用bool没事,是因为完成了一个隐式转换),而你用auto的话,想要得到意想中的类型,需要使用static_cast<bool>,再给auto。而这也不是特例,其适用于含有proxy class的class。

3. auto配合decltype,有时候会让人有意想不到的结果。让我引用标准的一个例子

       int i; int&& f(); auto x3a = i; // decltype(x3a) is int decltype(auto) x3d = i; // decltype(x3d) is int auto x4a = (i); // decltype(x4a) is int decltype(auto) x4d = (i); // decltype(x4d) is int& auto x5a = f(); // decltype(x5a) is int decltype(auto) x5d = f(); // decltype(x5d) is int&& auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int> decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression auto *x7a = &i; // decltype(x7a) is int* decltype(auto)*x7d = &i; // error, declared type is not plain decltype(auto)      



  

相关话题

  现代C/C++编译器有多智能?能做出什么厉害的优化? 
  程序员,女,想自学中医,计划5-8年内全面转行,怎么做才是靠谱的? 
  如何看待网上关于「阿里P7程序员、资深架构师不知 jvm、红黑树」一事的争议? 
  intel x86指令编码存在多个选择时如何选定opcode? 
  现在(2021年)OSGi的发展前景如何? 
  想裸写编译器,除了编译原理外还有那些资料可以参考?应该从什么开始写起?(用c/c++)? 
  是否有多人认为程序员的工作就是复制粘贴?为什么? 
  你是如何自学R语言的? 
  为什么要把程序写死? 
  怎么看待 Libra 使用 Rust 编写? 

前一个讨论
为什么 Go 语言在某些方面的性能还不如 Java?
下一个讨论
为什么说温室里长不出参天大树?





© 2025-03-28 - tinynew.org. All Rights Reserved.
© 2025-03-28 - tinynew.org. 保留所有权利