1,请牢牢记住一点auto的推断其实是跟template的推断一致的:
2,不能推断出一个模板中的另一个模板的类型,
3, 当auto作为函数的参数类型或者返回类型的时候auto类型的推断规则无效!按照模板类型的推断规则来.
case 1: auto
#include <iostream>
int main() { int x = 27; int& xx = x; const int cx = x; const int& rx = x; auto n_ = 10; //auto = int; auto x_ = x; //auto = int; auto xx_ = x;//auto = int; xx_ = 100; std::cout<<x<<std::endl; auto cx_ = cx; //auto = int; auto rx_ = rx; //auto = int; cx_ = 10; //ok, but x is also 27. rx_ = 100;//as same sa above. return 0; }
case 2:auto&
#include <iostream>
class Node{ public: Node()=default; ~Node(){ std::cout<<"destroy"<<std::endl; } };
int main() { int x = 27; int& xx = x; const int cx = x; const int& rx = x; auto& x_ = x; //auto = int; x_ = 1; //x = 1, now. std::cout<< x <<std::endl; auto& xx_ = x; //auto = int; xx_ = 2; std::cout<< xx_ <<std::endl; auto& cx_ = cx; //auto = const int; //cx_ = 3; //error. auto& rx_ = rx; //auto = const int; int* ptr = new int(2); //auto& p = &x; //error. auto& p =ptr; //auto = int* (&); p是一个对ptr的引用. *p = 10; std::cout<<p<<" "<<ptr<<std::endl; //地址一样. std::cout<<*p<<" "<<*ptr<<std::endl;//数据一致. delete ptr; int* ptr_two = new int(3); int* ptr_three = new int(4); std::cout<<ptr_two<<" "<<ptr_three<<std::endl; auto& p_two = ptr_two; p_two = ptr_three; //现在ptr_two和p_two都指向了ptr_three. new int(3)还留在堆内!!内存泄漏了. std::cout<<ptr_two<<" "<<p_two<<std::endl; std::cout<<*ptr_two<<" "<<*p_two<<std::endl; Node* ptr_node = new Node; auto& p_node = ptr_node; delete ptr_node; return 0; }
case3: const auto
#include <iostream>
int main() { int x = 27; const int cx = x; const int& rx = x; const auto y = 27; const auto x_ = 2; //auto = int; const auto xx_ = x; //auto = int; const auto cx_ = cx; //auto = int; const auto rx_ = rx; //auto = int; int* ptr = new int(10); int* ptr_two = new int(20); const auto p = ptr; //auto = int* , p的类型为int* const. std::cout<<p<<" "<<ptr<<std::endl; std::cout<<*p<<" "<<*ptr<<std::endl; *p = 30; std::cout<<*p<<" "<<*ptr<<std::endl; p = ptr_two; //error, p是一个顶层const. delete ptr; delete ptr_two; return 0; }
case4: auto&&
#include <iostream>
int main() { int x = 27; const int cx = x; const int& rx = x; auto&& xx = 27; //auto = int; auto&& x_ = x; //auto = int&; 引用折叠 && + & = &; x_ = 1; std::cout<< x <<std::endl; auto&& cx_ = cx; //auto = const int&; 引用折叠 && + & = &; auto&& rx_ = rx; //auto = const int&; 同上. return 0; }
case 5: const auto&
#include <iostream>
int main() { int x =27; const int cx = x; const int& rx = x; const auto& xx = 1; //auto = int; const auto& x_ = x; //auto = int&;发生了引用折叠&+&=&. const auto& cx_ = cx; //auto = int&;同上. const auto& rx_ = rx; //auto = int&;同上. int* ptr = new int(10); int* ptr_two = new int(20); const auto& p = ptr; //auto = int* const(&),p是一个对int* const类型的指针的引用!!!是引用!!!指针也能被引用!!. std::cout<<ptr<<" "<<p<<std::endl; std::cout<<*ptr<<" "<<*p<<std::endl; *p = 30; std::cout<<*ptr<<" "<<*p<<std::endl; //p = ptr_two; //error, 这是一个顶层const delete ptr; delete ptr_two; return 0; }
case 6:数组和auto
#include <iostream>
int number_array[]{1, 2, 3}; int* arr = new int[3]{4, 5, 6};
const int* const ptr = nullptr;
int main() { auto first = number_array; //auto = int* ; auto first_ = arr; //auto = int*; std::cout<<std::boolalpha<<std::is_same<int*, decltype(first)>::value<<" ";//输出: true. std::cout<<std::is_same<int*, decltype(first_)>::value<<std::endl; //true. auto& second = number_array; //auto = int[3]; second的类型是 int (&)[3]. auto& second_ = arr; //auto = int*; second_的类型是int*(&); std::cout<<std::boolalpha<<std::is_same<int(&)[3], decltype(second)>::value<<" ";//true std::cout<<std::is_same<int* (&), decltype(second_)>::value<<std::endl; //true auto&& third = number_array; //auto = int(&)[3]; third的类型是 int(&)[3]. auto&& third_ = arr; //auto = int*(&); third_的类型是 int*(&); std::cout<<std::boolalpha<<std::is_same<int(&)[3], decltype(third)>::value<<" ";//true std::cout<<std::is_same<int* (&), decltype(third_)>::value<<std::endl; //true const auto forth = number_array; //auto = int*; forth的类型为: int* const,一个顶层const的指针. const auto forth_ = arr; //auto = int*; forth_的类型为: int* const,顶层const. std::cout<<std::boolalpha<<std::is_same<int* const, decltype(forth)>::value<<" "; //true std::cout<<std::is_same<int* const, decltype(forth_)>::value<<std::endl; //true const auto& fifth = number_array; //auto = int[3]; fifth的类型为 const int(&)[3]; const auto& fifth_ = arr; //auto = int*; fifth的类型为 int* (&) const; std::cout<<std::boolalpha<<std::is_same<const int(&)[3], decltype(fifth)>::value<<" ";//true std::cout<<std::is_same<int* const(&), decltype(fifth_)>::value<<std::endl; //true return 0; }
case 7: 函数和auto
#include <iostream>
void function(const int& a, const int& b) { std::cout<<a<<" "<<b<<std::endl; }
int main() { auto func = function; //void (*)(const int&, const int&); (*func)(2, 0); auto& func1 = function; //void (const int&, const int&); func1(3, 4); return 0; }
看了这么多是不是发现其实跟模板类型推断一样呢?那么让我们来深入吧:
//c++提供了我们多种赋值的方式. int a = 1; int a(1); int a{3}; int a={2};
但是我们用auto的话呢?
auto a = 1; //auto = int; auto b(1); //auto = int; auto c{3}; //auto = std::initializer_list<int>; auto d={4}; //auto = std::initializer_list<int>;
还有:
auto list{1, 2, 3.0}; //error,竟然错了因为auto的类型被推断为std::initializer_list<int>但是3.0是一个float. template<typename T> void function(T param) { ...} f({1, 2, 3}); //error!!!!!!!! //由此我们可以看出不能推断出一个模板中的另一个模板的类型. auto createInitList() //error, 这里竟然是和模板类型的推断规则一致的. { return {1, 2, 3}; } std::vector<int> v; auto resetV= [&v](const auto& newV){ v = newV; } resetV({1, 2, 4}); //error,这里相当于是reset(const T& newV),用的也是模板类型的推断规则.
关于尾至返回类型:
#include <iostream> #include <vector>
template<typename Container, typename Index> auto function(Container& container, const Index& index)->decltype(container[index]) //如果使用了尾置返回类型auto是不会做任何事情的,其类型推断还是主要来自于decltype. //由于std::vector的T& operator[](index),返回的是一个引用所以decltype推断出的类型也是一个引用. { return container[index]; }
int main() { std::vector<int> v{1}; function(v, 0)=2; std::cout<<v[0]<<std::endl; //输出为2. return 0; }
错误的使用:
auto x; //error,不能知道x的类型. int x1 = 10; auto& ptr = &x1; //error.