为什么复制分配会导致 GCC 发出 -Wvirtual-move-assign 警告?

Why does copy assignment cause GCC to give a -Wvirtual-move-assign warning?

如果为 B 的实例调用移动分配,则以下 class 层次结构将在 GCC 中引起 [-Wvirtual-move-assign] 警告。

struct A {

    std::vector<int> v;

};

struct B : public virtual A {};

以下场景确实会导致出现警告

/*** SCENARIO 1 ***/
class C {

    B a;

    public:
        void foo(B& b) {

            b = a; // warning
            // or
            a = b; // warning

        }

};

/*** SCENARIO 2 ***/
void foo(const B& a, B& b) {

    b = a; // warning

}


int main() {

    /*** SCENARIO 3 ***/
    B b;
    std::vector<B> v1;
    v1.push_back(b); // warning

    /*** SCENARIO 4 ***/
    B b1;
    B b2;
    b1 = b2; // warning

    /*** SCENARIO 5 ***/
    B b3;
    b3 = B(); // warning

}

即使稍后再次使用分配的对象,警告仍然会出现。除了场景 5 涉及右侧的右值并因此涉及移动赋值外,我希望(实际上我希望)在这些场景中发生复制赋值而不是移动赋值。如果是这样,那么为什么会出现此警告?表达式中的某处是否实际发生了移动赋值?

你好像误报了。 Why does gcc warn about calling a non-trivial move assignment operator with std::tuple and virtual inheritance? 的答案表明 gcc 比实际需要更频繁地发出此警告,而 clang 则不会。所以我加强了你的例子(就像在那个答案中所做的那样)并将它交给了 clang。

struct A {
    std::vector<int> v;
};

struct AA : public virtual A {};
struct AB : public virtual A {};

struct B : public AA, AB {};

使用此设置,clang 仅针对 b3 = B(); 行发出警告(场景 5)。它接受其他情况,表明 gcc 只是偏执。 (要么是 gcc 发出误报,要么是 clang 有错误。不过,您的分析似乎是正确的,所以可能是前者。)