您的位置:首页 > 编程语言 > C语言/C++

Effective C++: auto类型推断.

2016-03-30 00:00 344 查看
1,请牢牢记住一点auto的推断其实是跟template的推断基本一致也有稍微的不同体现在std::initializer_list:

2,不能推断出一个模板中的另一个模板的类型(template<template<typenaem T> class A>);
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; //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&

#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

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


语法(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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: