亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Item30 Familiarize yourself with perfect forwarding failure cases

2019-11-11 04:02:40
字體:
來源:轉載
供稿:網友

這個系列的文章來自于Effective Modern C++的讀書筆記,我抽取了其中比較重要的,不容易理解的,平常我們開發過程中也不太在意的一些Item進行分析。

? 在C++11中最為顯著的一個新特性,當屬完美轉發了,是的它很完美,和它的名字一樣,轉發兩字意味著一個函數將其參數傳遞給另外一個函數,第二個函數的目標則是接收來自于第一個函數傳遞過來的對象,轉發字體現出第二個函數接收到的對象應該和第一個參數傳遞過來的是相同的,因此如果采用值傳遞的方式就沒有辦法達到效果了,因為拷貝后的對象是原來的對象是兩個不同的對象,如果想在第二個函數中操作傳遞過來的對象也達不到效果,因為操作的是復制后的對象,并不是原對象。如果采用指針傳遞的話,的確是可以達到轉發的效果。但是這要求用戶必須傳遞指針,因此算不上完美。

? 完美轉發意味著不僅僅要轉發對象本身,還要轉發它附帶的屬性,它的類型,左值或者是右值,是否是constvolatile,根據Item24中的介紹,這里只有通用引用可以做到。下面是一個完美轉發的例子。

template<typename T>void fwd(T&& param) { // 這里是通用引用 f(std::forward<T>(param));}

不僅僅可以轉發一個參數,還可以結合可變參數轉發多個參數,如下:

template<typename T>void fwd(Ts&&... params) { f(std::forward<Ts>(params)...);}

這個和STL中的make_sharedmake_unique是一樣的,make_shared源碼如下:

template<typename _Tp, typename... _Args> inline shared_ptr<_Tp> make_shared(_Args&&... __args){ typedef typename std::remove_const<_Tp>::type _Tp_nc; return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(), std::forward<_Args>(__args)...);}

? 然而完美轉發并不完美,在一些場合下會因為類型推導錯誤導致轉發了錯誤的類型,最后導致執行失敗,本文則是通過講解這些失敗的場景,讓我們知道哪些場景下完美轉發無法正常工作。

統一初始化

void f(const std::vector<int>& v);f({1, 2, 3}); // {1, 2, 3}會隱式轉換成std::vector<int>,因為vector帶有列表初始化的構造函數

? 因為std::vector<int>帶有列表初始化的構造函數,所以{1, 2, 3}可以隱式構造成std::vector<int> 。

vector(initializer_list<value_type> __l, // 初始化列表 const allocator_type& __a = allocator_type()) : _Base(__a) { _M_range_initialize(__l.begin(), __l.end(), random_access_iterator_tag()); }

? 但是如果將{1, 2, 3}通過完美轉發給f的話則導致編譯失敗。

fwd({1, 2, 3});

? 上面的調用編譯失敗了,其原因是因為{1, 2, 3}進行模版推導失敗了,所以找不到匹配的fwd函數,編譯出錯的信息如下:

note: candidate template ignored: couldn't infer template argument 'T'

? 這就是完美轉發遇到的第一個失敗的例子,解決這個問題的方法也很簡單,在Item2中介紹過,盡管模版推導無法推導出初始化列表的正確類型,但是auto可以,所以上面的代碼改成如下的形式就可以順利運行。

auto il = {1, 2, 3};fwd(il);

0或者NULL 作為空指針

? 在Item8中提到過,當0或者是NULL作為指針類型傳遞給一個模版函數的時候,會推導出錯誤的類型,把0或者NULL作為int類型,很顯然0或者NULL無法被當作指針類型進行完美轉發,解決這個問題也很簡單,使用C++11中的nullptr替換即可。

僅僅聲明整型的靜態const數據成員

class Widget {public: static const std::size_t MinVals = 28;};

? 上面的MinVals只是聲明了,但是還沒有在類外進行定義,任何一個學過C++的人都知道靜態成員變量需要在類外進行初始化,但是static const是一個例外,它可以不用在類外進行定義,但是它在內存中不會分配實際的存儲。所以下面的代碼運行一切正常。

void f2(std::size_t val) { ....}f2(Widget::MinVals);

? 編譯期就會直接把Widget::MinVals 替換成28了,然后進行實際的調用了。一旦對Widget::MinVals進行取地址的操作,會導致MinVals去尋找定義,但是上面的代碼沒有在類外定義MinVals,這就導致在鏈接階段報錯,找不到Widget::MinVals的定義。

const std::size_t *p = &(Widget::MinVals);

? 靜態const數據成員的這個特點在完美轉發的場景下也會帶來同樣的問題,完美轉發是通過通用引用來轉發參數,通用引用本質上是指針,因此在這個場景下如果沒有在類外定義MinVals也會在鏈接的時候報錯。

template<typename T>void fwd(T&& param) { // 這里是通用引用 f(std::forward<T>(param));}fwd(Widget::MinVals);

函數重載和函數模版

void f(int (*pf)(int)); //函數f接收一個函數作為參數int PRocessVal(int value);int processVal(int value, int priority);fwd(processVal); // 編譯失敗

? 上面的fwd通過完美轉發processVal但是編譯失敗,因為模版的類型推導無法推導出processVal的類型。這就是在函數重載的場景下模版類型推導失敗的例子。同樣如果使用函數模版替換模版重載的話,模版類型推導依然失敗,無法推導出函數模版的類型。

template<typename T>T workOnVal(T param) { .....}fwd(workOnVal);

解決上面這兩個問題也很簡單,就是主動賦予函數和函數模版的類型,代碼如下:

using ProcessFuncType = int(*)(int);ProcessFuncType processValPtr = processVal;fwd(processValPtr);fwd(static_cast<ProcessFuncType>(workOnVal));

位域

最后一種完美轉發失效的情況是位域,代碼如下:

struct ipv4Header { std::uint32_t version:4, IHL:4, DSCP:6, ECN:2, totalLength:16; .....};void f(std::size_t sz);IPv4Header h;f(h.totolLength);fwd(h.totolLength); //編譯失敗

? 上面的代碼中位域h.totolLength被傳遞給f的時候可以正常工作,當傳遞給fwd完美轉發的時候編譯失敗,因為fwd是一個模版,模版的參數是通用引用,本質上是一個引用,C++標準規定一個非const的引用無法引用一個位域字段。這個規定也是有原因的,因為位域可能只是一個int的部分字節,沒有一個確定的地址,沒辦法通過指針指向位域,引用本質上就是指針,自然沒辦法引用位域了。既然沒辦法對一個位域進行引用那么可以通過拷貝位域的值后然后再進行完美轉發,代碼如下:

auto length = static_cast<std::uint16_t>(h.totolLength);fwd(length);

總結

? 總結來說,完美轉發失敗的例子總共有三類,第一類就是模版無法進行有效的類型推導,例如上文提到的函數重載,模版重載,統一初始化等,第二類則是模版推導的類型是錯誤的,例如上文中提到的0或者NULL 作為空指針,第三類則是引用無法指向傳遞過來的參數,例如上文中提到的位域和靜態const數據成員。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
色偷偷888欧美精品久久久| 国产午夜精品视频| 亚洲女人天堂色在线7777| 国产精品久久久久久久久久新婚| 国产日韩精品一区二区| 久久久精品久久久久| 国产精品99久久久久久久久久久久| 国产精品r级在线| 一区二区三区 在线观看视| 欧美在线一级视频| 国产精品日韩久久久久| 欧美激情亚洲精品| 超碰97人人做人人爱少妇| 日本久久久久久久| 国色天香2019中文字幕在线观看| 亚洲桃花岛网站| 国产精品精品久久久久久| 中文字幕在线看视频国产欧美在线看完整| 中文字幕一区二区三区电影| 在线播放国产一区二区三区| 一区二区在线视频播放| 欧美日韩国产成人在线观看| 色av中文字幕一区| 国产精品偷伦免费视频观看的| 8x拔播拔播x8国产精品| 国产精品69精品一区二区三区| 国产精品偷伦视频免费观看国产| 欧美伊久线香蕉线新在线| 欧美激情伊人电影| 欧美成人精品不卡视频在线观看| 欧美成人久久久| 久久成年人视频| 91夜夜揉人人捏人人添红杏| 国产精品无av码在线观看| 亚洲精品视频在线观看视频| 91在线视频导航| 国产精品美女午夜av| 久久乐国产精品| 91九色蝌蚪国产| 色综合久久精品亚洲国产| 国产91对白在线播放| 国产精品免费一区二区三区都可以| 亚洲国内高清视频| 91九色单男在线观看| 国产成+人+综合+亚洲欧美丁香花| 日韩av成人在线观看| 国产精品久久久久久久久免费| 伊人伊人伊人久久| 97超级碰碰人国产在线观看| 亚洲国产私拍精品国模在线观看| 国产精品日韩欧美综合| 色婷婷av一区二区三区久久| 亚洲精品91美女久久久久久久| 欧美黄色免费网站| 日韩中文在线中文网三级| 亚洲欧美国产精品专区久久| 国产福利视频一区二区| 一区二区在线视频播放| 国产成人短视频| 在线看片第一页欧美| 日韩成人av在线播放| 国产精品一区久久| 亚洲日本成人网| 亲爱的老师9免费观看全集电视剧| 亚洲japanese制服美女| 国产美女搞久久| 性欧美视频videos6一9| 亚洲欧美日韩图片| 国产精品v片在线观看不卡| 欧美激情在线视频二区| 中文字幕亚洲欧美一区二区三区| 日韩欧美aⅴ综合网站发布| 久久精品国产2020观看福利| 国产成人午夜视频网址| 国产日韩精品在线| 高清一区二区三区四区五区| 日韩中文字幕视频在线观看| 91超碰中文字幕久久精品| 国产乱肥老妇国产一区二| 日韩精品极品毛片系列视频| 欧美激情第一页xxx| 神马国产精品影院av| 久久久成人av| 日韩va亚洲va欧洲va国产| 中文字幕亚洲欧美| 欧美性猛交xxxx久久久| 亚洲美女精品久久| 欧美激情精品久久久久久变态| 日韩欧美国产一区二区| 日韩免费av片在线观看| 欧美电影在线观看高清| 日本久久中文字幕| 久久av在线播放| 亚洲人成网站免费播放| 亚洲视频999| 亚洲美女在线观看| 亚洲激情视频在线播放| 日本精品一区二区三区在线| 狠狠做深爱婷婷久久综合一区| 亚洲欧洲在线看| 久久久久久国产精品| 日韩美女av在线| 亚洲第一区在线观看| 欧美另类69精品久久久久9999| 国产精品一二区| 日韩美女在线观看一区| 亚洲精品久久久久中文字幕欢迎你| 久久99青青精品免费观看| 色综合伊人色综合网| 午夜精品久久久久久久99热浪潮| 精品国内亚洲在观看18黄| 成人网中文字幕| 久久免费国产视频| 亚洲女人初尝黑人巨大| 成人在线国产精品| 国产欧美亚洲视频| 中文字幕亚洲欧美一区二区三区| 国产精品久久久久久久久久久久久久| 5278欧美一区二区三区| 国产成人高清激情视频在线观看| 亚洲欧美成人精品| 亚洲人成网7777777国产| 亚洲精品自拍偷拍| 精品亚洲一区二区三区| 欧美放荡办公室videos4k| 26uuu亚洲国产精品| 久久综合久久美利坚合众国| 国产欧美中文字幕| 精品视频久久久久久久| 国产精品爽爽ⅴa在线观看| 欧美极品少妇xxxxⅹ喷水| 国外成人在线播放| 亚洲成人免费在线视频| 欧美激情国产日韩精品一区18| 亚洲最新中文字幕| 91在线视频导航| 亚洲国产91色在线| 国产精品视频yy9099| 美女久久久久久久| 国产日韩欧美夫妻视频在线观看| 国产在线精品一区免费香蕉| 欧美夫妻性生活xx| 欧美国产视频日韩| 日韩在线观看免费| 亚洲欧美自拍一区| 欧美日韩一区二区精品| 高清在线视频日韩欧美| 26uuu久久噜噜噜噜| 欧美亚洲国产日韩2020| 色综合色综合网色综合| 亚洲国产成人久久| 精品中文字幕在线观看| 欧美亚洲国产精品| 91在线免费视频| 亚洲性无码av在线| 黄色成人av在线| 国产精品色婷婷视频| 亚洲欧美变态国产另类| 欧洲美女免费图片一区| 精品中文字幕久久久久久| 亚洲欧洲日本专区| 欧美一级黑人aaaaaaa做受| 日韩av黄色在线观看| 亚洲一区二区久久久久久久|