Двойное освобождение дочернего объекта после использования конструктора копирования - PullRequest
0 голосов
/ 09 июня 2018

Мне трудно понять, почему (кажется, что) объект разрушается дважды.

Если я создаю объект класса (B), который содержит объект другого класса (A) ия копирую этот объект.скопированный объект уничтожается дважды.Хотя это выглядит так.Я не могу понять этот вывод.

Я создал следующий (минимум?) Пример, который, кажется, вызывает мою проблему:

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

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

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

    }

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

    void add(T item) {
        /* Irrelevant */
    }

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++)
        {
            characters.add(input[i]);
        }
    }

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

    ~B() {

    }


private:
    A<char> characters;
};

template <class T>
uint64_t A<T>::ctr = 0;

int main(int argc, char *argv[]) {
    B b1 = B((char *)"b1", 2);
    B b2 = B(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 destructor - object id: 3
class A destructor - object id: 3
class A destructor - object id: 1

объектный идентификатор 3 уничтожается дважды, а объектный идентификатор 2 вообще не уничтожается.

Я использую следующий компилятор: Microsoft (R) C / C ++ Оптимизирующая версия компилятора 19.14.26429.4

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

Ответы [ 2 ]

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

В этой строке возникает путаница.

characters = A<char>(b2.characters);

A оператор сгенерированного по умолчанию оператора копирует объект 3 в объект 2, включая myCtr.

myCtr не const, поэтому он может измениться в течение своей жизни.Если вам нужно, чтобы значение оставалось неизменным, сделайте его const.

Вот версия вашего класса, которая будет вести себя так, как вы ожидаете.

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

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

    }

    A<T>& operator=(const A<T> &a2) {
        // Copy what's needed from a2 here.
        return *this;
    }

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

    void add(T item) {
        /* Irrelevant */
    }

private:
    const uint64_t myCtr;
    static uint64_t ctr;
};
0 голосов
/ 09 июня 2018

Вы должны следовать правилу 5 .Если вы реализуете нетривиальный деструктор, копируете / перемещаете назначение / конструкцию, вы должны реализовать все 5, или дать вескую причину, почему нет, или удалить их.

Вы внедрили Destory и скопируйте ctor.Вы пренебрегли другими 3. Добавьте их.

Что еще characters = A<char>(b2.characters); ваш экземпляр копирования вызывает назначение копирования.Который вы не отслеживаете, вот почему ваш счет выключен.Вы назначаете на прилавке.

...