C ++ переместить присваивание неинициализированному объекту? - PullRequest
0 голосов
/ 10 июня 2018

Как следует до: Двойное освобождение дочернего объекта после использования конструктора копирования

Я следовал правилу 5, как предложено.Но теперь кажется, что назначение перемещения происходит на неинициализированном объекте (для идентификатора объекта 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

В случае, если вы проголосуете против.Пожалуйста, укажите почему.Я с радостью постараюсь улучшить свой вопрос.

Редактировать:

Кажется, что только компилятор Visual C ++ для платформы x86 вызывает эту проблему.Он отлично работает с g ++ (x86 и x64), clang (x86 & x64) и msvc (x64).Это затрудняет выяснение происхождения этой проблемы для меня.

1 Ответ

0 голосов
/ 10 июня 2018

В конструкторе

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).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...