![](/img/trans.png)
[英]Why synthesized copy-assignment operator is defined as deleted if the class has a reference member?
[英]Why does copy-and-swap in a base class cause the copy-assignment operator to be implicitly deleted in the derived class?
僅在GCC和Clang 中測試,基類中存在按值傳遞的復制賦值運算符(在實現復制和交換(或復制和移動)習慣用法時很有用)導致復制賦值運算符在派生類被隱式刪除。
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.