簡體   English   中英

默認構造函數阻止調用emplace_back

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM