Effective C++: auto类型推断.

1,请紧紧记住一点auto的推断实际上是跟template的推断基本一致也有稍微的不一样体如今std::initializer_list:node

2,不能推断出一个模板中的另外一个模板的类型(template<template<typenaem T> class A>);
 3, 当auto做为函数的参数类型或者返回类型的时候auto类型的推断规则无效!按照模板类型的推断规则来.ios

case 1: autoc++

 #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&express

#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; //p的类型是: int*(&); 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&spa

#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; //ptr的类型是:int* const(&),auto = int*; 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.net

#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;
}

看了这么可能是不是发现其实跟模板类型推断同样呢?那么让咱们来深刻吧:code

//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.

 

语法(C++14):

decltype(auto) variable initializer  	(since C++14)
decltype(auto) function                 (since c++14)

针对: decltype(auto) function咱们能够:

decltype(auto) function(int x, int y)

{

  return (x+y); //其实至关于调用 auto function(int x, int y)->decltype(x+y)

}

 

If the declared type of the variable is decltype(auto), the keyword auto is replaced with the expression (or expression list) of its initializer, and the actual type is deduced using the rules for decltype.

针对: decltype(auto) variable initializer咱们能够:

decltype(auto) i =10; //i的类型为 int;

int x=10;

decltype(auto) y=(x); //至关于decltype((x)) y = x; 所以y的类型为 int&.

decltype(auto) list={1, 2}; //error, 由于{1, 2}不是表达式.

auto list_={1, 2}; //ok!

参考: https://my.oschina.net/u/2516597/blog/538605

相关文章
相关标签/搜索