C ++将赋值移动到未初始化的对象?

时间:2018-06-10 11:10:00

标签: c++ visual-c++ constructor move-assignment-operator

跟进: Double free of child object after using the copy constructor

我按照建议遵循5的规则。 但现在似乎移动分配发生在未初始化的对象(对象id 0)上?我希望它从对象3移动到对象2.

我创建了以下(最小?)示例,这似乎触发了我的问题:

#include <stdio.h>
#include <stdint.h>

class A
{
public:
    A()
    {
        myCtr = ++ctr;
        printf("class A default Constructor - object id: %u\n", myCtr);
    }

    A(const A &a2) {
        myCtr = ++ctr;
        printf("class A copy constructor - object id: %u\n", myCtr);

    }

    A(A &&a2) {
        myCtr = a2.myCtr;
        a2.myCtr = 0;

        printf("class A move constructor - object id: %u\n", myCtr);

    }

    A & operator=(const A &a2) {
        myCtr = ++ctr;

        printf("class A copy assignment - from object id: %u - to object id: %u\n", a2.myCtr, myCtr);

        return *this;
    }

    A & operator=(A &&a2) {
        printf("class A move assignment - from object id: %u - to object id: %u\n", a2.myCtr, myCtr);

        if (this != &a2) {
            //myCtr = a2.myCtr;
            //a2.myCtr = 0;
        }

        return *this;
    }

    ~A()
    {
        printf("class A destructor - object id: %u\n", myCtr);
    }

private:
    uint64_t myCtr;
    static uint64_t ctr;
};

class B
{
public:
    B() {

    }

    B(char * input, uint32_t len) {
        for (uint32_t i = 0; i < len; i++)
        {
            /* do something */
        }
    }

    B(const B &b2) {
        characters = A(b2.characters);
    }

    B(B &&b2) {
        characters = A(b2.characters);
    }

    B & operator=(const B &b2) {
        characters = A(b2.characters);
    }

    B & operator=(B &&b2) {
        characters = A(b2.characters);
    }

    ~B() {

    }


private:
    A characters;
};

uint64_t A::ctr = 0;

int main(int argc, char *argv[]) {
    B b1 = B((char *)"b1", 2);
    B b2 = b1;

    return 0;
}

这会产生以下输出:

class A default Constructor - object id: 1
class A default Constructor - object id: 2
class A copy constructor - object id: 3
class A move assignment - from object id: 3 - to object id: 0
class A destructor - object id: 3
class A destructor - object id: 2
class A destructor - object id: 1

这是我没想到的路线:

class A move assignment - from object id: 3 - to object id: 0

期望:

class A move assignment - from object id: 3 - to object id: 2

我正在使用以下编译器:Microsoft(R)C / C ++优化编译器版本19.14.26429.4

如果你投票失败。请说明原因。我很乐意尝试改进我的问题。

编辑:

似乎只有针对x86平台的Visual C ++编译器才会出现此问题。它适用于g ++(x86&amp; x64),clang(x86&amp; x64)和msvc(x64)。这使得我更难找出这个问题的根源。

1 个答案:

答案 0 :(得分:1)

在构造函数

B(const B &b2) {
    characters = A(b2.characters);
}

首先创建A类型的临时对象,然后将其移动到characters变量。这就是移动分配发生的原因。

尝试通过以下方式替换此构造函数:

B(const B &b2) : characters(b2.characters)
{   
}

您将获得预测的结果(https://ideone.com/yqvINu,VS示例:http://rextester.com/PTPZKR93068)。