簡體   English   中英

為什么基類中的復制和交換會導致派生類中的復制賦值運算符被隱式刪除?

[英]Why does copy-and-swap in a base class cause the copy-assignment operator to be implicitly deleted in the derived class?

僅在GCCClang 中測試,基類中存在按值傳遞的復制賦值運算符(在實現復制和交換(或復制和移動)習慣用法時很有用)導致復制賦值運算符在派生類被隱式刪除。

Clang 和 GCC 同意這一點; 為什么會這樣?

示例代碼:

#include <string>
#include <iostream>

struct base {
    base() {
        std::cout << "no-arg constructor\n";
    }
    base(const base& other) :
        str{other.str} {
        std::cout << "copy constructor\n";
    }
    base(base&& other) :
        str{std::move(other.str)} {
        std::cout << "move constructor\n";
    }
    base& operator=(base other) {
        std::cout << "copy assigment\n";
        str = std::move(other.str);
        return *this;
    }
    base& operator=(base&& other) {
        std::cout << "move assigment\n";
        str = std::move(other.str);
        return *this;
    }

    std::string str;
};

struct derived : base {
    derived() = default;
    derived(derived&&) = default;
    derived(const derived&) = default;
    derived& operator=(derived&&) = default;
    derived& operator=(const derived&) = default;
};

derived foo() {
    derived ret;
    ret.str = "Hello, world!";
    return ret;
}

int main(int argc, const char* const* argv) {

    derived a;
    a.str = "Wat";
    a = foo(); // foo() returns a temporary - should call move constructor
    return 0;
}

在您的代碼中,不會刪除派生副本分配。 但是被刪除的是移動分配,因為[class.copy.assign]/7.4 ,它指出如果基類上移動分配的重載決議不明確,則刪除默認的移動分配運算符。

編譯器無法判斷是調用operator=(base)還是operator=(base&&)來移動基類。


這始終是一個問題,即使您嘗試將一個基類對象直接分配給另一個基類對象。 因此,同時擁有兩個重載並不實際。 我不清楚為什么你需要兩者。 據我所知,您可以刪除operator=(base&&)重載而不會產生不良影響。

[class.copy.assign] / 7 A默認復制/類移動賦值運算符X被定義為已刪除如果X具有:
(7.4) - ...無法復制/移動的直接基類M ,因為重載決議 (16.3) 在應用於查找M的相應賦值運算符時會導致歧義...

base的移動分配不明確; 它有兩個賦值運算符,都接受一個右值。 觀察這不編譯

base a, b;
a = std::move(b);

因此, derived移動分配最終定義為已刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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