auto
1.简单用法
从c++11开始,auto从原先的赋予变量自动生命周期变成了变量自动类型推断
简单例子:
int a = 100; auto aa = a;
此时aa的类型为int,值为100;
我们也可以这样使用auto:
auto a = 100; //int auto b = 100.0f; //float auto c = 100.0; //double auto d = "auto"; //const char*
auto的语义消失问题(auto会将const和&引用忽略掉):
【此处对于初学者而言,记得要先分清&引用和&取地址的区别,指针和取地址并不会被auto忽略】
int a = 1; //int int& a1 = a; //int& auto a2 = a1; //int const int b = 1; //const int auto b1 = b; //int
如果想要auto带上引用或const,写法如下:
int a = 1; //int int& a1 = a; //int& auto& a2 = a1; //int& const int b = 1; //const int const auto b1 = b; //const int
特殊情况,auto会将初始化列表视为std::initializer_list,且不允许直接初始化,必须使用=:
auto a = { 1,2,3 }; //std::initializer_list<int>
那么问题来了,为什么auto可以自动推断变量类型,auto是如何实现的呢?
auto的类型推断,与模板函数的类型推断极为类似,请参考模板函数的类型推导{待补充}
auto作用于编译过程,使用auto并不会降低程序运行效率。
且auto不会降低编译的效率,因为编译器在任何情况下都需要获得右操作数的类型去与左操作数类型比较。
2.实用层面
1.当然如果我们在使用如最开始的例子一样,用auto取推断一个简单对象(比如例子中的int)从实用层面而言时完全没有必要的,因为这时auto并不如显示的定义出来更加清晰明确
但是当我们在处理命名空间极其繁杂的大工程时,可以选择使用auto代替一长串的类型定义
namespace nameA { namespace nameB { namespace nameC { struct structD{ int a; float b; double c; string d; }; } } }
before:
nameA::nameB::nameC::structD* a= new nameA::nameB::nameC::structD;
after:
auto a = new nameA::nameB::nameC::structD;
这种用法在保证了易读的条件下也能做到代码简洁~
2.在for中使用auto
可以参考范围for{待补充}
这里只着重说一下语义上的区别
需求:老板要给每一位员工发一颗苹果
class employee { public:bool have_apple = false; }; void give_apple(employee &e) { //give an apple to the people e.have_apple = true; }
std::vector<employee> employees; employees.resize(100);
before:
for (int i = 0; i < employees.size(); i++) give_apple(employees[i]);
after:
for (auto &em : employees) give_apple(em);
虽然说从代码实现来看没什么区别,但是从语义上来讲
前者更像是:叫0号到最后一号员工分别进来领苹果,而后者更像是,叫每一位员工分别进来领苹果,显然从语义上来说使用auto是更为合理的写法
反思【不要停止思考 --某不愿透露姓名的屑饼】:
我们为什么要用auto而不是使用using namespace来减少代码量呢?
因为using namespace并不是被推荐使用的写法,当namespace A和namespace B中有同名成员m时,如果你既using namespace A 又 using namespace B,此时直接使用m会导致冲突;
所以更推荐不使用using namespace,而是老老实实的用A::m,B::m。
在c++14中{待补充}:
允许auto作为函数返回值
支持直接使用decltype(auto)来推断原始类型