![](/img/trans.png)
[英]vector::push_back insists on using copy constructor though a move constructor is provided
[英]Why does using the move variant of std::vector::push_back invoke the moved item's copy constructor?
這里有一些代碼無法編譯,因為push_back試圖在MoveOnlyClass中調用復制構造函數,該構造函數被刪除:
class MoveOnlyClass
{
public:
MoveOnlyClass() {};
MoveOnlyClass& operator=(const MoveOnlyClass& other) = delete;
MoveOnlyClass(const MoveOnlyClass& other) = delete;
};
int main()
{
std::vector<MoveOnlyClass> vec;
vec.push_back(std::move(MoveOnlyClass()));
}
為什么會這樣? 當然,向量應該調用的唯一東西是移動構造函數。 將對象移動到向量中的正確方法是什么?
刪除復制構造函數/復制賦值函數也會隱式刪除move-constructor / move賦值函數。 如果您打算使對象可移動但不可復制,則還需要default
移動構造函數。
class MoveOnlyClass
{
public:
MoveOnlyClass() {};
MoveOnlyClass& operator=(const MoveOnlyClass& other) = delete;
MoveOnlyClass(const MoveOnlyClass& other) = delete;
MoveOnlyClass& operator=(MoveOnlyClass&& other) = default;
MoveOnlyClass(MoveOnlyClass&& other) = default;
};
//Will now compile as you expect
int main()
{
std::vector<MoveOnlyClass> vec;
vec.push_back(std::move(MoveOnlyClass()));
}
另外, std::move(T())
是多余的; 像這樣構造一個就地對象已經使它成為一個R值,並且當你不需要時使用std::move
可能會阻止某些類型的編譯器優化(比如Copy Ellision)。
@Xirema的答案密切關於代碼中問題的處理,並解釋了為什么會這樣。
我只是想用語言規范的適當摘錄來支持它,以使事情正式化。 所以來自[class.copy.ctor¶8] :
(8)如果類X的定義沒有顯式地聲明一個移動構造函數, 那么當且僅當一個非顯式的構造函數被隱式聲明為默認的
- (8.1) X沒有用戶聲明的拷貝構造函數 ,
為此我們應該添加聲明,因為刪除仍然是聲明。 因此,根據這一點,我們不會在您的情況下獲得隱式聲明的移動構造函數 ,因為我們已經有了一個用戶聲明的復制構造函數 。
此外,在[dcl.fct.def.delete¶3]下 :
通過使用復制構造函數和復制賦值運算符的已刪除定義, 然后提供移動構造函數和移動賦值運算符的默認定義, 可以使類不可復制,即僅移動。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.