Есть ли утечка памяти в этом случае?

_Доброго денёчка всем. Прохожу тему на указатели и ссылки. Делаю упражнение на тему "написать программу, вызывающую утечку памяти". Смысл идеи "учись на ошибках и запомни как делать не нуна, а то будет ай-ай-ай". В книге приведён пример такой логической ошибки, когда в функции выполняется создание экземпляра класса, для которого оператором new в функции выделяется память. Затем ссылка на объект передаётся в main для дальнейших издевательств.. _Ну вот я нечто в этом роде и написал. А потом малость подправил, и теперь не уверен, что в моем коде есть утечка памяти. Помогите, корифеи, Христа ради.
 // Логическая ошибка, приводящая к утечке памяти.
#include <iostream>
using namespace std;
 
class Detail
{
public: Detail (int length, int width);
        ~Detail ();
        int GetLength() const { return itsLength; }
        int GetWidth() const { return itsWidth; }
        void SetLength (int length) { itsLength = length; }
        void SetWidth (int width) { itsWidth = width; }
private:
    int itsLength;
    int itsWidth;
};
 
Detail::Detail (int length, int width)
{
    cout << " Calling constructor...\n";
    itsLength = length;
    itsWidth = width;
}
 
Detail::~Detail()
{
    cout << " Calling destructor...\n";
}
 
Detail & MakeDetail ();
 
int main()
{
    cout << "\n\n";
    Detail Det1(600, 510);
    cout << " Det.1 Length: " << Det1.GetLength() << " mm.\n";
    cout << " Det.1 Width: " << Det1.GetWidth() << " mm.\n";
    cout << "\n";
    Detail Det2 = MakeDetail();  
    cout << " Det.2 Length: " << Det2.GetLength() << " mm.\n";
    cout << " Det.2 Width: " << Det2.GetWidth() << " mm.\n";
    cout << "\n\n";
    system ("pause");
    return 0;
}
 
Detail & MakeDetail ()
{
    cout << " Calling MakeDetail...\n";
    Detail * NewDetail = new Detail (0, 0);
    NewDetail->SetLength(704);
    NewDetail->SetWidth(510);
    return *NewDetail;
}
Output:Calling constructor... Det.1 Length: 600 mm. Det.1 Width: 510 mm.Calling MakeDetail... Calling constructor... Det.2 Length: 704 mm. Det.2 Width: 510 mm.Для продолжения нажмите любую клавишу . . . Caling destructor... Caling destructor...Деструктор, как видите, вызывается дважды. Или таки память от *NewDetail не очищена?
14 ответов

Сделайте еще конструктор копий и посмотрите на результаты


Хах, третий раз переписываю ответ Скорее всего проблема есть, так как стековые и объекты из кучи разрушаются по разному, но тут у меня сомнения насчет ссылки: то есть я не уверен, что оно должно быть закорапчено, но delete вызван не будет в любом случае, те утечка естьНа самом деле здесь идеально бы пошел scoped_ptr


Или таки память от *NewDetail не очищена?
После завершения программы ОС сама все почистит, но не хорошо на это опираться.


Сделайте еще конструктор копий и посмотрите на результаты
Здесь ссылка, то есть копирования нет


Здесь ссылка, то есть копирования нет
Вот тут есть:
Detail Det2 = MakeDetail();
ибо Det2 не ссылка.


Здесь ссылка, то есть копирования нет
Здесь должно быть:
Detail Det2 = MakeDetail();


_Т. е. утечка есть, так как явно эта выделенная память в программе не очищается, да? Спасибо, значит я всё правильно натупил.


_Т. е. утечка есть, так как явно эта выделенная память в программе не очищается, да?
Да, есть. После этого
Detail Det2 = MakeDetail();
память, выделенная в MakeDetail остается висеть и ничто на неё не указывает, а значит нет возможности её освободить.Вот такой main:
int main()
{
    while(true)
         MakeDetail();
    return 0;
}
вот такие результаты в диспетчере задач:


Croessmah, ***, да с той стороны то не ссылка, но утечка в любом случае получается


Спасибо всем за ответы. Буду курить дальше.


А зачем вообще нужна память, на которую ни что не указывает? Зачем её было выделять?


Зачем её было выделять?
вот ответ:
Прохожу тему на указатели и ссылки. Делаю упражнение на тему "написать программу, вызывающую утечку памяти".


Detail & Det2 = MakeDetail();Смыл этой строки мне непонятен... Это значит что я создаю ссылку на тип Detail и присваиваю этой ссылке другую ссылку? Поэтому я убрал амперсант перед Det2.


Поэтому я убрал амперсант перед Det2.
Убрали амперсанд - получили копирование и невозможность далее освободить память.