c++??復(fù)制消除問題解決示例詳析
錯(cuò)誤示范
push_back 這么寫是錯(cuò)的:
template<class T>
class threaded_message_queue {
public:
using lock = std::unique_lock<std::mutex>;
void push_back(T t) {
{
lock l(_m);
_data.push_back(std::move(t));
}
_cv.notify_one();
}
}
};//入?yún)?nbsp;T t 導(dǎo)致了調(diào)用者在這里會(huì)發(fā)生一次臨時(shí)對(duì)象 TMP 的復(fù)制,稍后在函數(shù)退出點(diǎn)處 TMP 還會(huì)被隱式析構(gòu)。所以這個(gè)寫法不是良構(gòu)。
至于函數(shù)體中的 std::move(t) 也就是聊勝于無(wú)了,它并不會(huì)讓 t 少掉 TMP 的復(fù)制,僅僅只是少掉了 t 到 _data 的一次復(fù)制而已。
正確工作
做模板類開發(fā)時(shí),經(jīng)常會(huì)遇到 push_back 的這種場(chǎng)景。
正確的 push_back 應(yīng)該包含左值復(fù)制和右值移動(dòng)兩種語(yǔ)義,一般來(lái)說(shuō)像是這樣子:
template<class T>
class threaded_message_queue {
public:
using lock = std::unique_lock<std::mutex>;
void emplace_back(T &&t) {
{
lock l(_m);
_data.template emplace_back(std::move(t));
}
_cv.notify_one();
}
void push_back(T const &t) {
{
lock l(_m);
_data.push_back(t);
}
_cv.notify_one();
}
}
};注意右值加上移動(dòng)語(yǔ)義才是一對(duì)搭配。T t 和移動(dòng)語(yǔ)義在一起只是一種錯(cuò)覺。
你還可以加上一個(gè) push_back 的移動(dòng)語(yǔ)義:
void push_back(T &&t) {
{
lock l(_m);
_data.template emplace_back(std::move(t));
}
_cv.notify_one();
}這是因?yàn)榘凑占s定,emplace_back 通常采用模板變參并實(shí)現(xiàn) T 類的原位構(gòu)造。這個(gè)話題我在 C++ 中的原位構(gòu)造函數(shù)及完美轉(zhuǎn)發(fā) - 寫我們自己的 variant 包裝類 已經(jīng)有過一定的討論,這里就不詳述了。
X-class
hicc::debug::X 是一個(gè)專門用來(lái)調(diào)試 RVO,In-place construction,Copy Elision 等等特性的工具類,它平平無(wú)奇,只不過是在若干位置埋點(diǎn)冰打印 stdout 文字而已,這可以讓我們直觀觀察到哪些行為實(shí)際上發(fā)生了。
X-class 在構(gòu)造函數(shù)的入?yún)⒉糠钟邢嗨频臉?gòu)造:
namespace hicc::debug {
class X {
std::string _str;
void _ct(const char *leading) {
printf(" - %s: X[ptr=%p].str: %p, '%s'\n", leading, (void *) this, (void *) _str.c_str(), _str.c_str());
}
public:
X() {
_ct("ctor()");
}
~X() {
_ct("dtor");
}
X(std::string &&s)
: _str(std::move(s)) {
_ct("ctor(s)");
}
X(std::string const &s)
: _str(s) {
_ct("ctor(s(const&))");
}
X &operator=(std::string &&s) {
_str = std::move(s);
_ct("operator=(&&s)");
return (*this);
}
X &operator=(std::string const &s) {
_str = s;
_ct("operator=(const&s)");
return (*this);
}
const char *c_str() const { return _str.c_str(); }
operator const char *() const { return _str.c_str(); }
};
} // namespace hicc::debug以上就是c++ 復(fù)制消除問題解決示例詳析的詳細(xì)內(nèi)容,更多關(guān)于c++ 復(fù)制消除問題的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)字符串分割的實(shí)例
這篇文章主要介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)字符串分割的實(shí)例的相關(guān)資料,希望通過本文能幫助到大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-10-10
C++教程之進(jìn)制轉(zhuǎn)換的實(shí)現(xiàn)方法
在C++中進(jìn)行進(jìn)制轉(zhuǎn)換可以通過標(biāo)準(zhǔn)庫(kù)函數(shù)或自定義算法實(shí)現(xiàn),本文主要為大家整理了兩種常見場(chǎng)景的轉(zhuǎn)換方法及示例代碼,有需要的小伙伴可以根據(jù)需求進(jìn)行選擇2025-04-04
C語(yǔ)言MFC導(dǎo)出dll回調(diào)函數(shù)方法詳解
這篇文章主要為大家介紹了C語(yǔ)言MFC導(dǎo)出dll回調(diào)函數(shù)方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
C/C++ chrono簡(jiǎn)單使用場(chǎng)景示例詳解
這篇文章主要介紹了C/C++ chrono簡(jiǎn)單使用場(chǎng)景示例詳解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2025-06-06
C++多態(tài)與虛擬之C++編譯器對(duì)函數(shù)名的改編(Name?Mangling)
在Windows?DLLs中,使用C++編寫的DllMain()等callback函數(shù)需避免C++編譯器進(jìn)行name?mangling,因此需使用extern?"C",這篇文章主要介紹了C++多態(tài)與虛擬:C++編譯器對(duì)函數(shù)名的改編(Name?Mangling),需要的朋友可以參考下2024-04-04
C語(yǔ)言數(shù)學(xué)公式來(lái)實(shí)現(xiàn)土味表白
大家好,本篇文章主要講的是C語(yǔ)言數(shù)學(xué)公式來(lái)實(shí)現(xiàn)土味表白,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12
C++ float轉(zhuǎn)std::string 小數(shù)位數(shù)控制問題
這篇文章主要介紹了C++ float轉(zhuǎn)std::string 小數(shù)位數(shù)控制問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11

