Возврат ссылки на данные memeber в cpp - PullRequest
0 голосов
/ 17 ноября 2011

Что я знаю, возвращать ссылку на локальную переменную - это то же самое, что возвращать указатель на локальную переменную, и это вызывает утечку памяти в C ++.

Но относится ли это к элементам данных?

Код:

class MyClass
{
public:
    std::string& getId();
private:
    std::string id;
};

MyClass std::string& getId()
{
    return id;
}


int main()
{
    MyClass* c = new MyClass;
    std::string brokenRef = c->getId();
    // or may be std::string& brokenRef = c->getId();
    delete c;

    cout << brokenRef << endl; // <<< this should be a ref to unknown location, correct?

}

Спасибо.

Ответы [ 5 ]

1 голос
/ 17 ноября 2011

В строке

std::string brokenRef = c->getId();

Вы создаете новый экземпляр строки и инициализируете его строкой, на которую ссылается ссылка, возвращаемая getId ().С этого момента brokenRef живет полностью независимой жизнью от MyClass объекта.Поэтому brokenRef счастливо пережил MyClass объект, который вы уничтожили.

Вы могли бы достичь желаемого эффекта, назначив ссылку на ссылочную переменную:

std::string& brokenRef = c->getId();

В дополнение к этому, я думаю, высмешанные термины утечка памяти и висячий указатель ( висячий указатель ).Возвращение указателя или ссылки на член не вызывает утечек памяти.Но их использование (разыменование) после уничтожения объекта (так что память, в которой хранились элементы, освобождается и они становятся висящими ), вызывает неопределенное поведение и весьма вероятный сбой.

1 голос
/ 17 ноября 2011

Да, это применимо.Даже если ваш экземпляр MyClass не является строго локальным по отношению к основному, но динамически размещается и освобождается перед ссылкой.Однако имеет тот же эффект.

Код в том виде, в каком он есть, правильный, потому что вы копируете строку, пока она действительна.Закомментированная эталонная версия действительно неработающая.

0 голосов
/ 17 ноября 2011

Вы получите какое-то значение, но это будет какое-то случайное значение, которое, поскольку объект, который содержит его, было уничтожено.

в идеале я бы удалил и установил бы его на нуль

, поэтому в вашемНапример,

 c=null;

Объектно-ориентированный C ++ имеет те же ограничения на время жизни объекта, что и каждый язык на основе ОО

Жизненный цикл объекта начинается, когда он создается, и заканчивается, когда он уничтожается.В определении класса C ++ функция-член с тем же именем в качестве класса является конструктором.Это функция, которая вызывается автоматически при создании экземпляра класса.Конструкторы обычно используются для инициализации элементов данных объекта в их состояние по умолчанию, но также могут использоваться для распределения ресурсов (память, файлы и т. Д.).Для любого класса может быть объявлено несколько функций конструктора, каждая из которых принимает разные типы аргументов, обеспечивая различные способы инициализации экземпляров.Конструктор по умолчанию для класса - это конструктор этого класса, который можно вызывать без каких-либо аргументов.Конструктор по умолчанию для класса будет сгенерирован автоматически, если ни один конструктор не был явно объявлен для этого класса.Конструктор копирования для класса - это конструктор, который можно вызвать для копирования объекта этого класса (он имеет единственный аргумент соответствующего типа).Конструктор копирования вызывается, когда, например, объект аргумента передается по значению в функцию или когда объект инициализируется значением другого объекта.Copyconstructor для класса будет сгенерирован автоматически, если для этого класса не было явно объявлено ни одного конструктора копирования.Функция-член с тем же именем в качестве класса с ведущей тильдой (~) является деструктором. Это функция, которая вызывается автоматически при удалении объекта. Деструктор обычно используется для освобождения любой памяти, выделенной для объекта (и может такжеосвободить любые другие ресурсы, полученные во время построения). Конструкторы и деструкторы не требуются в определениях классов.

Существует несколько способов создания объектов в программе на C ++.Один из них - определить переменную как принадлежащую к определенному классу, либо как глобальную переменную, либо как локальную переменную внутри блока.Когда объявление встречается во время выполнения программы, выделяется место для объекта и вызывается конструктор, если таковой имеется, для объекта.Точно так же, когда переменная объекта выходит из области видимости, ее деструктор вызывается автоматически.Другой способ создания объекта - объявить переменную, которая является указателем на класс объекта, и вызвать новый оператор C ++, который выделит пространство для объекта и вызовет конструктор, если таковой имеется, для объекта. В этом случае переменная-указатель должнабыть явно освобождены с оператором удаления.Конструктор для объекта выполняется при вызове new, а деструктор выполняется при вызове delete. Объект также может быть создан с помощью явного использования конструктора в выражении.

Когда класс является производным от другого класса, он наследует конструктор и деструктор своего родительского класса.Родительские конструкторы вызываются до производных конструкторов.Деструкторы вызываются в обратном направлении, начиная от производного класса вверх по его родительской цепочке.

Подробнее здесь http://www.objs.com/x3h7/cplus.htm

0 голосов
/ 17 ноября 2011

, пока ваш MyClass не удален, ссылка действительна.

или если бы вы объявили его как переменную стека, то, пока его область действия, члены в экземпляре класса действительны.

0 голосов
/ 17 ноября 2011

Это нормально в вашем примере, потому что вы присваиваете string, если вы превратите его в string&, тогда он станет недействительным, как только вы delete c.

(и это точно не вызывает утечку памяти).

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