简体   繁体   English

为什么基类中的复制和交换会导致派生类中的复制赋值运算符被隐式删除?

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

Tested only in GCC and Clang , the presence of a pass-by-value copy assignment operator in the base class (useful when implementing the copy-and-swap (or copy-and-move) idiom) causes the copy assignment operator in the derived class to be implicitly deleted.仅在GCCClang 中测试,基类中存在按值传递的复制赋值运算符(在实现复制和交换(或复制和移动)习惯用法时很有用)导致复制赋值运算符在派生类被隐式删除。

Clang and GCC agree on this; Clang 和 GCC 同意这一点; why is this the case?为什么会这样?

Example code:示例代码:

#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;
}

In your code, the derived copy assignment is not deleted.在您的代码中,不会删除派生副本分配。 What is deleted though is the move assignment, because of [class.copy.assign]/7.4 , which states that a defaulted move assignment operator is deleted if overload resolution for the move assignment on a base class is ambiguous.但是被删除的是移动分配,因为[class.copy.assign]/7.4 ,它指出如果基类上移动分配的重载决议不明确,则删除默认的移动分配运算符。

The compiler wouldn't be able to tell whether to call operator=(base) or operator=(base&&) in order to move the base class.编译器无法判断是调用operator=(base)还是operator=(base&&)来移动基类。


This is always a problem, even if you try to move assign a base class object directly to another base class object.这始终是一个问题,即使您尝试将一个基类对象直接分配给另一个基类对象。 So it is not really practical to have both overloads.因此,同时拥有两个重载并不实际。 It is not clear to me why you need both.我不清楚为什么你需要两者。 From what I can tell you can remove the operator=(base&&) overload without ill effect.据我所知,您可以删除operator=(base&&)重载而不会产生不良影响。

[class.copy.assign]/7 A defaulted copy/move assignment operator for class X is defined as deleted if X has: [class.copy.assign] / 7 A默认复制/类移动赋值运算符X被定义为已删除如果X具有:
(7.4) - ...a direct base class M that cannot be copied/moved because overload resolution (16.3), as applied to find M 's corresponding assignment operator, results in an ambiguity... (7.4) - ...无法复制/移动的直接基类M ,因为重载决议 (16.3) 在应用于查找M的相应赋值运算符时会导致歧义...

base 's move assignment is ambiguous; base的移动分配不明确; it has two assignment operators both accepting an rvalue.它有两个赋值运算符,都接受一个右值。 Observe that this doesn't compile :观察这不编译

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

For this reason, move assignment of derived ends up defined as deleted.因此, derived移动分配最终定义为已删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如果类具有引用成员,为什么将综合的复制分配运算符定义为已删除? - Why synthesized copy-assignment operator is defined as deleted if the class has a reference member? 与代理类复制分配运算符怎么办? - What to do with proxy class copy-assignment operator? 派生类在基类中被删除时是否会有隐式复制构造函数或赋值运算符? - Would a derived class ever have an implicit copy constructor or assignment operator when it's deleted in the base class? 复制和交换基类和派生类 - copy & swap in base and derived class 复制派生类的赋值运算符 - Copy assignment operator for derived class 在具有所有const数据成员的类中实现复制赋值运算符是否有意义? - Does it make sense to implement the copy-assignment operator in a class with all const data members? 如何在赋值运算符中使用noexcept与copy-and-swap惯用法? - How to use noexcept in assignment operator with copy-and-swap idiom? 使用复制和交换惯用法移动构造函数和赋值运算符 - move constructor and assignment operator impletemented using copy-and-swap idiom 为什么引用类型成员会导致隐式声明的复制赋值运算符被删除 - Why do reference type members cause implicitly-declared copy assignment operator to be deleted 在派生类中复制构造和赋值运算符 - Copy construct and assignment operator in the derived class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM