当现在允许使用虚拟基本移动分配运算符时,会有危险吗? [英] Danger with virtual base move assignment operators when they are now allowed to be used?

查看:263
本文介绍了当现在允许使用虚拟基本移动分配运算符时,会有危险吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这涉及C ++问题的解决方案 http:/ /www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1402 。摘要:

This concerns the resolution of C++ Issue http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1402 . Summary:


template<typename T>
struct wrap
{
   wrap() = default;

   wrap(wrap&&) = default;
   wrap(const wrap&) = default;

   T t;
};

struct S {
   S(){}
   S(const S&){}
   S(S&&){}
};

typedef wrap<const S> W;

// Error, defaulted move constructor of "wrap<const S>" is deleted!
W get() { return W(); }


(问题是我们收到此错误即使编译器可以简单地使用S的拷贝构造函数,正如它在用户显式地写入wrap的move构造函数时所做的那样。该问题被解决为在重载分辨率期间忽略删除的移动构造函数(和赋值运算符) ,因此根据需要使用上面的复制构造函数。)

(The issue is that we are getting an error for this snippet, even though the compiler could simply use the copy constructor of "S", as it does when the user explicitly writes the move constructor of "wrap". The issue was resolved to ignore deleted move constructors (and assignment operators) during overload resolutions, hence using the copy constructor above as desired.)

当解析 ,对此决议发表了以下评论:

When the resolution was drafted, the following comment was made about this resolution:


与复制相关的隐式/默认移动操作没有其他限制。这意味着在虚拟基础中的移动分配是危险的(编译器应该警告)[...]但是我们在Batavia决定,我们不会保留所有C ++ 03代码隐式移动操作,我认为

There are no additional restrictions for implicit/defaulted move operations relative to copy. This means that move assignment in a virtual base is dangerous (and compilers should probably warn) [...] But we decided in Batavia that we weren't going to preserve all C++03 code against implicit move operations, and I think this resolution provides significant performance benefits.

有人可以描述对虚拟基本移动赋值运算符的关注吗?

Can someone please describe what the concern with virtual base move assignment operators is?

推荐答案

请考虑:

#include <iostream>

struct A
{
    A() = default;
    A(const A&) = default;
    A(A&&) = default;
    A& operator=(const A&) {std::cout << "operator=(const A&)\n"; return *this;}
    A& operator=(A&&) {std::cout << "operator=(A&&)\n"; return *this;}
};

struct B
    : virtual public A
{
};

struct C
    : virtual public A
{
};

struct D
    : public B,
      public C
{
};

int
main()
{
    D d1, d2;
    d1 = std::move(d2);
}

我相信这个程序应该输出:

I believe this program should output:

operator=(A&&)
operator=(A&&)

对我来说,它实际上输出:

For me it actually outputs:

operator=(const A&)
operator=(const A&)

但我认为这只是一个ang (用-std = c ++ 1y编译)。如果我对输出应该是什么是正确的,那么危险是移动赋值运算符被调用两次。这是无害的(虽然可能是昂贵的)使用副本赋值运算符,但不是移动赋值运算符。

But I think this is just a clang bug (compiled with -std=c++1y). If I am correct about what the output should be, then the danger is that the move assignment operator is called twice. This is harmless (though potentially expensive) with the copy assignment operator, but not with the move assignment operator.

这篇关于当现在允许使用虚拟基本移动分配运算符时,会有危险吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆