《深入应用C++11代码优化与工程级应用》第1章学习记录

《深入应用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大佬

    《深入应用C++11代码优化与工程级应用》第1章学习记录

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/341545

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午1:08
下一篇 2023年3月2日 上午1:08

相关推荐