C++11类型系统

C++ feels like a new language. -- Bjarne Stroustrup

  1. 类型推演
  2. 右值引用
  3. 通用引用
  4. 剖析std::move
  5. 剖析std::forward
  6. 总结

类型推演

增强了的「类型系统」是C++11最大的优化亮点之一,为此需要深入剖析「类型推演」的工作机理,并能灵活地运用auto, decltype,这是C++11最重要的基石。

template与auto

C++98早已具备类型推演的能力,用于模板的类型推演。

C++11中,autotemplate的类型推演能力基本类似,只存在唯一的差异:Braced Initialization,或称为Universal Initialization

非常量的左值引用

需要注意的是,推演auto &r2 = r, auto &cr2 = cr时,即使r(int&), cr(const int&)是引用变量,需要去除引用后再尝试类型推演,因为使用「引用变量」等价于使用其「引用对象」本身。

常量的左值引用

因为const T&const auto&已经具备了const的属性,当const的左值对象赋予它所发生的自动类型推演,其模板参数T,及其auto的类型无需推演为const属性。


指向非常量的指针

指针的推演能力与引用类似。

需要注意auto *p = &i; auto p = &i两种写法的不一样,一种是显式的指针类型,另外一种完全依赖于auto的类型推演能力。

指向常量的指针

与指向非常量的指针推演机制一致,在此不再冗述。


按值传递

Pass-By-Value,经过拷贝之后,两者之间已无任何瓜葛,为此const的处理机制有别于其他情况。



但存在两类特殊的,遗留的C-Style情况,为保证兼容性,存在特殊的类型推演机制。

遗留的C-style字符串

遗留的C-style函数

通用引用:Universal Reference

所谓Universal Reference,因为其能Can bind to anything,所以称为「通用引用」,具有如下方面的特点:

  • Can bind to lvalue or rvalue;
  • Can bind to const/non-const, volatile/non-volatile, or both;
  • So, it can bind to anything.

需要注意的是,Universal Reference并非「右值引用(Rvalue Reference)」,即使它们两者都有类似的T &&的修饰符。规则非常简单,Universal Reference具备两个最基本的特征:

  • T &&, auto&&: 必须具备的句法结构
  • type reduce:必须发生类型推演

可以简单归纳之,Universal Reference出现于如下两种常见:

template <typename T>
void f(T&& t);

auto&& r = i;

Universal Reference类型推演也存在特殊性:

  • Universal Reference持有左值时,发生Reference Collapsing机制。例如auto&& t = i,当auto推演为int&auto&& t推演为int& && t,而int& &&经过Reference Collapsing机制,被进一步规约为int&,与原来它持有左值刚好匹配。

  • Universal Reference持有右值时,推演规则较为直观,例如auto&& t = 10,当auto被推演为int,则auto&& t推演为int&& t,与原来它持有右值刚好匹配。



通用初始化:Braced Initialization

这是templateauto类型推演能力之间存在的唯一差别。

右值引用

「右值引用」(Rvalue Reference) 与「通用引用」(Universal Reference)是两个不同的概念,非常容易混淆,本文试图揭示两者之间的本质的差异。

左值与右值

「左值」与「右值」并非C++11的产物,早已是C++类型系统的一部分了,并且两者之间存在明显的区别。

举个例子,进一步明细两者之间的差异。此处使用auto&&Universal Reference,它会根据「左值」自动推演为「左值引用」,而「右值」推演为「右值引用」。

右值引用

C++98中,只存在「左值引用」,遗恨缺失「右值引用」的概念,也因此丢失了部分性能优化的空间。C++11中引入了「右值引用」,弥补之前的过失,结合「移动」(move)的机制,进一步提高了C++在特殊场景的性能。

所谓右值引用,即「右值」的引用;之前惯称的「引用」,其实是「左值引用」的简称。「左值引用」只能引用「左值」,「右值引用」只能引用「右值」。

通用引用

「通用引用」并非「左值引用」,即使它们之间都具有&&的语法结构。「通用引用」即可以持有「左值」,也可以持有「右值」,是一种「通用」的引用类型。而「右值引用」只能引用「右值」。

特征

  • void f(Object&& o),因为未发生类型推演,为右值引用
  • template <typename T> void f(std::vector<T>&& v),因为不是T&&的句法结构,为右值引用

可以简单归纳之,「通用引用」出现于如下两种常见:

template <typename T>
void f(T&& t);

auto&& r = i;

样例

std::vector新增加的「右值引用」的push_back,及其「通用引用」的emplace_back是最好的案例。

剖析std::move

C++11实现

当传递左值时

经过如下的类型推演过程,当传递「左值」时,std::move强制转为换「右值引用」。

当传递右值时

经过如下的类型推演过程,当传递「右值」时,std::move顺水推舟,传递「右值引用」。综上述,借助「通用引用」的能力,std::move其实完成了「无条件的」右值引用转换规则。

C++14改进实现

剖析std::forward

C++11实现

当传递左值时

经过如下的类型推演过程得知,当传递「左值」时,std::forward完成「左值」的「转发」机制。

当传递右值时

经过如下的类型推演过程得知,当传递「右值」时,std::forward也完成「右值」的「转发」机制。为此,std::forward的机制,完成了C++11的「完美转换」(Perfect Forward)的机制。

C++14改进实现

习惯用法

回顾

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容