[英]Default constructor prevents from calling emplace_back
似乎添加默認構造函數會阻止調用emplace_back
並產生錯誤消息:“靜態斷言失敗:類型不可分配”(gcc 5.3 with -std = c ++ 14)。 這是一個簡單的代碼,說明了這個問題:
class A {
public:
int a;
A() = default;
A(int a) {
this->a = a;
}
A(A const & a) = delete;
A& operator =(A const & a) = delete;
A(A && a) = default;
A& operator =(A && a) = default;
};
int main() {
A a(4);
std::vector<A> vec;
vec.emplace_back(std::move(a)); // Error: type is not assignable
return 0;
}
刪除默認構造函數時,錯誤消失了! 此外,如果定義了默認構造函數(即使它什么都不做),錯誤也會消失:
class A {
public:
int a;
A() {
}
A(int a) {
this->a = a;
}
A(A const & a) = delete;
A& operator =(A const & a) = delete;
A(A && a) = default;
A& operator =(A && a) = default;
};
int main() {
A b;
A a(4);
std::vector<A> vec;
vec.emplace_back(std::move(a)); // Error gone
return 0;
}
似乎“A()=默認;” 是導致問題的原因。 這是編譯器的一部分正常行為還是一個錯誤?
這是一個libstdc ++ bug(編輯:報告為bug 69478 )。
簡而言之,libstdc ++的std::vector
,與此相關,使用std::uninitialized_copy
(與移動迭代器配對)在重新分配時移動元素,如果類型很簡單且迭代器的引用類型是可分配的,則減少為std::copy
(即,概念上使用的賦值運算符是可用的)。
然后, std::copy
用於指向普通類型的指針(或者在我們的例子中,包含指針的move_iterator
)又被優化為對memmove
的調用以及對is_copy_assignable
的檢查。 當然,在這種情況下檢查是錯誤的,因為uninitialized_copy
與移動迭代器配對,只需要移動可構造的東西。
如果您沒有默認構造函數或者默認構造函數是用戶定義的,那么該類並不簡單,因此您不會遇到觸發此錯誤的代碼路徑。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.