代码之家  ›  专栏  ›  技术社区  ›  M. Winter

为什么在复制构造函数中分配联合成员会崩溃?

  •  0
  • M. Winter  · 技术社区  · 7 年前

    QBrush int )并通过使用 type 成员

    class X
    {
    public:
        X(const QBrush &brush)
            : type(0), b(brush) { }
        X(int integer)
            : type(1), i(integer) { }
        X(const X &other)
            : type(other.type)
        {
            if (type == 0)
                b = other.b;
            else i = other.i;
        }
    
        ~X() { }
    
    private:
        int type;
        union
        {
            QBrush b;
            int i;
        };
    };
    
    int main(int argc, char *argv[])
    {
        X x = X(QBrush(Qt::red));
        X y = X(x);
        return 0;
    }
    

    我很惊讶这个程序崩溃了。目前我没有调试器,所以我只知道它在的复制构造函数中崩溃 X 指定笔刷时。注意,当我将复制构造函数代码替换为

    X(const X &other)
        : type(other.type), b(other.b), i(other.i)
    { }
    

    QBrush公司 是Qt提供的一些类。我想这次崩溃与这个类的内部结构有关。但我不知道。有人知道发生了什么吗?

    2 回复  |  直到 7 年前
        1
  •  2
  •   geza    7 年前

    这里有一个bug:

    X(const X &other)
        : type(other.type)
    {
        if (type == 0)
            b = other.b;  // b is not constructed yet
        else i = other.i;
    }
    

    b 尚未构建,但您调用 operator=

    使用 new(&b) QBrush(other.b) b 使用复制构造函数。

        2
  •  2
  •   ephemient    7 年前

    boost::variant<QBrush, int> / std::variant<QBrush, int> (C++17)而不是自己尝试管理。在联合体中放置非POD类型时,必须手动处理构造和销毁,目前缺少一些情况。至少,您需要一个自定义析构函数,规则3表示,除了复制构造函数之外,还应该提供赋值运算符。

    X(const X &other) : type(1) {
        *this = other;
    }
    ~X() {
        if (type == 0) b.~QBrush();
    }
    X& operator=(const X &other) {
        if (type == 0) b.~QBrush();
        type = 1;
        if (other.type == 0) {
            new(&b) QBrush(other.b);
            type = 0;
        } else i = other.i;
        return *this;
    }
    

    type 因此,如果 QBrush