《深入应用C++11代码优化与工程级应用》第1章学习记录
1.1 类型推导
1.1.1 auto类型推导
auto并不能代表一个实际的类型声明,只是一个类型声明的“占位符”。
使用auto声明的变量必须马上初始化,以让编译器推断出它的实际类型,并在编译时将auto占位符替换为真正的类型。
auto的推导规则:(cv限定符:const和volatile的统称)
(1)当不声明为指针或引用时,auto的推导结果和初始化表达式抛弃引用和cv限定符后类型一致。
eg. int x = 0;
const auto e = x; //e->const int
auto f = e; //f->int
(2)当声明为指针或引用时,auto的推导结果将保持表达式的cv属性。
eg.int x = 0;
const auto& g = x; //g->const int&
auto h = g; //h->const int&
auto的限制:
(1)auto不能用于函数参数。
(2)auto不能用于非静态成员变量。
(3)auto无法定义数组。
(4)auto无法推导出模板参数。
eg.
[root@192 C++11]# cat funcautodemo.cpp
#include <iostream>
using namespace std;
struct Foo
{
auto var1_ = 0; //auto不能用于非静态成员变量
static const auto var2_ = 0;
};
int func(auto x) //auto不能用于函数参数
{
int i = x;
return 0;
}
template <typename T> struct Bar {};
int main()
{
int arr[10] = {0};
auto aa = arr;
auto rr[10] = arr; //auto无法定义数组
Bar<int> bar;
Bar<auto> bb = bar; //auto无法推导出模板参数
return 0;
}
[root@192 C++11]# g++ funcautodemo.cpp -o funcautodemo -std=c++11
funcautodemo.cpp:5:5: error: non-static data member declared with placeholder ‘auto’
5 | auto var1_ = 0;
| ^~~~
funcautodemo.cpp:9:10: error: use of ‘auto’ in parameter declaration only available with ‘-std=c++14’ or ‘-std=gnu++14’
9 | int func(auto x)
| ^~~~
funcautodemo.cpp: In function ‘int main()’:
funcautodemo.cpp:21:10: error: ‘rr’ declared as array of ‘auto’
21 | auto rr[10] = arr;
| ^~
funcautodemo.cpp:24:9: error: invalid use of ‘auto’
24 | Bar<auto> bb = bar;
| ^~~~
funcautodemo.cpp:24:13: error: template argument 1 is invalid
24 | Bar<auto> bb = bar;
| ^
funcautodemo.cpp:24:20: error: cannot convert ‘Bar<int>’ to ‘int’ in initialization
24 | Bar<auto> bb = bar;
| ^~~
| |
| Bar<int>
1.1.2 decltype关键字
获知表达式类型
上面提到的auto需要把变量初始化,编译器才能推导出类型,如果不想初始化,只是声明就能得到类型,这时就需要用到decltype。
eg.
int x = 0;
decltype(x) y = 1; //y->int
decltype(x+y) z = 0; //z->int
const int& i = x;
decltype(i) j = y; //j->const int&
const decltype(z) *p = &z; //p->const int *
decltype(z) *pi = &z; //pi->int*
decltype(pi) *pp = &pi ; //pp->const int **
decltype(exp)的推导规则:
(1)exp是标识符、类访问表达式,decltype(exp)和exp的类型一致
eg.
class Foo
{
public:
static const int Number = 0;
int x = 0;
};
int n = 0;
volatile const int& x = n;
decltype(n) a = n; //a->int
decltype(x) b = n; //b->volatile const int&
decltype(Foo::Number) c = 0; //c->const int
Foo foo;
decltype(foo.x) d = 0; //d->int
(2)exp是函数调用,decltype(exp)和返回值的类型一致
eg.
int& func_int_r(void); //左值
int&& func_int_rr(void); //右值
int func_int(void); //纯右值
const int& func_cint_r(void); //左值
const int&& func_cint_rr(void); //右值
const int func_cint(void); //纯右值
const Foo func_cfoo(void); //纯右值
int x = 0;
decltype(func_int_r()) a1 = x; //a1->int&
decltype(func_int_rr())b1 = 0; //b1->int&&
decltype(func_int()) c1 = 0; c1->int
decltype(func_cint_r()) a2 = x; //a2->const int&
decltype(func_cint_rr())b2 = 0; //b2->const int&&
decltype(func_cint()) c2 = 0; //c2->int
decltype(func_cfoo()) ff = Foo(); //ff->const Foo
注意:c2为int,const被忽略了,而ff是const Foo,const没有被忽略,是因为按照C++11规范里的描述,函数返回值的int是纯右值,只有类类型可以携带cv限定符,其他的一般忽略掉cv限定符。
(3)其他情况,如果exp是一个左值,则decltype(exp)是exp类型的左值引用,否则和exp类型一致。。
eg.
struct Foo {int x;};
const Foo foo = Foo();
decltype(foo.x) a = 0; //a->int
decltype((foo.x)) b = a; //b->const int&
int n = 0,m = 0;
decltype(n+m) c = 0; //c->int
decltype(n+=m) d = c; //d->int&
原文链接: https://www.cnblogs.com/snake-fly/p/12657612.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;
也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/341545
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!