C ++, это приведет к утечке памяти? - PullRequest
0 голосов
/ 08 декабря 2011

Я знаю, что не могу получить ссылку на локальную переменную. такие как:

int& func1()
{
    int i;
    i = 1;
    return i;
}

И я знаю, что это правильно, но я должен удалить его после вызова func2 ()

int* func2()
{
    int* p;
    p = new int;


       *p = 1;
        return p;
}

int main()
{
    int *p = func2();
    cout << *p << endl;
    delete p;
    return 0;
}

Если функция такая:

MyClass MyFunction()
{
    return new MyClass;
}

Полное определение MyClass:

class MyClass
{
public:
    MyClass() : num(1){}
    MyClass(MyClass*) : num(10){}
    int num;
};

Это приведет к утечке памяти?

Как мне этого избежать? функция возвращает объект, а не указатель, так как я могу удалить его?

PS: код взят из книги "Размышления на С ++" Глава 10. Оригинальный код:

Picture frame(const Pictrue& pic)
{
    // Picture has a constructor Picture(*P_Node)
    // Frame_Pic derives from P_Node
    // So the constructor Picture(*P_Node) will implicitly convert Frame_Pic to Picture.
    return new Frame_Pic(pic);
}

Ответы [ 6 ]

3 голосов
/ 08 декабря 2011
MyClass MyFunction() 
{     
return new MyClass; 
} 

Это на самом деле неправильно. Вы возвращаете указатель. так должно быть

MyClass* MyFunction()

если ваша функция такая же, как я упоминал выше, и если вы не удаляете ее после использования, это приведет к потере памяти.

Как мне этого избежать? функция возвращает объект, а не указатель, так как я могу удалить его?

это ошибка компиляции. Поэтому точка ее удаления не поднимется

2 голосов
/ 08 декабря 2011

Если вы удалите указатель, возвращенный из функции, утечки памяти не будет. Однако это подвержено ошибкам, поскольку это означает, что каждый клиент функции должен знать, что он должен удалить возвращаемое значение. Гораздо лучше использовать интеллектуальный указатель (shared_ptr или unique_ptr в соответствии с семантикой).

То же самое относится к примеру Picture. Если этот объект правильно управляет своими ресурсами (т.е. удаляет в деструкторе и имеет хороший конструктор копирования и operator= (в соответствии с правилом трех ), то утечки памяти нет.

1 голос
/ 08 декабря 2011

С вашим обновленным MyClass, в котором есть конструктор указателей, я полагаю, вы должны написать:

MyClass MyFunction() {
    MyClass *ptr = new MyClass;
    MyClass retval(ptr);
    delete ptr;   // the dynamically-allocated object isn't needed any more
    return retval;
}

Это безопасно для исключений, поскольку конструктор MyClass не может генерировать, но какобщее правило, которое вы действительно никогда не должны вызывать new, не помещая результат прямо в умный указатель:

MyClass MyFunction() {
    std::unique_ptr<MyClass>(new MyClass);
    return MyClass(ptr);
}

В любом случае, это довольно абсурдная ситуация - если вы собираетесь возвращать по значению, естьнет никакой причины вызывать new вообще:

MyClass MyFunction() {
    MyClass tmpvalue;
    return &tmpvalue; // doesn't actually return the pointer, just an object
                      // constructed from it
}

И поскольку значение указателя даже не используется конструктором указателя, вы также можете написать:

MyClass MyFunction() {
    return 0; // returns an object constructed from a null pointer
}

В исходном коде вашей цитаты из книги, я предполагаю, что класс Picture имеет член данных типа P_Node*, в котором он хранит значение указателя и вызывает delete для этого указателя в своем деструкторе.Надеемся, что автор также что-то делает с конструктором копирования и оператором назначения копирования Picture, чтобы предотвратить двойное освобождение после копирования.У меня нет книги, поэтому я не могу проверить свое предположение, но код Picture должен показать, как это делается.

[Правка: о, это одна из книг Кенига и Му,Они (более чем) компетентны, поэтому, безусловно, их класс Picture правильно обрабатывает ресурс.Если это не так, то это потому, что это умышленный пример Doing It Wrong.]

0 голосов
/ 08 декабря 2011
MyClass MyFunction()
{
    return new MyClass;
}

неверно, потому что оператор new возвращает указатель на MyClass, но ваша функция возвращает MyClass, а не MyClass *

0 голосов
/ 08 декабря 2011

Это так же, как ваш пример "func2".кто когда-либо называл «рамкой», нужно в конце освободить возвращающуюся картинку.

0 голосов
/ 08 декабря 2011

Простая проверка будет такой:

  • Если вы используете N число new в своей программе, то вы должны использовать N количество совместимых 1 delete в вашем программа для предотвращения утечки памяти 2 .

Так ты это делаешь? Да, в первом случае (в котором вы делаете new int) вы делаете это. Нет утечки памяти.

А остальная часть поста мне не совсем понятна!


1. Под совместимым delete я имею в виду, если вы используете new в форме ptr = new T[M], то совместимый delete должен иметь форму delete []ptr. Аналогично, delete ptr совместим с ptr = new T.

2. Конечно, если вы используете некоторые умные указатели, вам не нужно явно указывать delete.

...