Есть три основных проблемы с вашим кодом прямо сейчас:
Прежде всего, ваш закомментированный вызов деструктора ~ReceivedMessage()
вообще не должен быть там.В C ++ деструктор объектов автоматически вызывается, когда заканчивается время жизни объекта (либо когда он выходит из области видимости, либо когда вызывается delete
, если он был динамически выделен с помощью new
).Хотя в некоторых ситуациях необходим явный вызов деструктора (например, «размещение нового»), с этими ситуациями вы вряд ли столкнетесь.
Во-вторых, ваше объявление RecievedMessage a(sc, type, vals);
во внутреннем if
не заменяет значение a
во внешней области видимости.Это просто создает другую переменную с тем же именем, которая затеняет внешний a
, тогда как return &a;
во внешней области видимости может ссылаться только на внешний a
.Внутренний a
больше не существует в этой точке, поскольку он вышел из области видимости.
Чтобы решить эту проблему, вместо этого назначьте новое значение для a
с помощью оператора =
исоздание временного ReceivedMessage
:
if (!vals.empty()) {
a = ReceivedMessage(sc, type, vals);
}
Это должно работать до тех пор, пока для ReceivedMessage
.
определено правильное operator=
(неявно или иначе). В-третьих, ваша функциявозвращая указатель на локальную переменную a
.Поскольку объекты в C ++ уничтожаются, как только они выходят из области видимости, a
больше не существует к моменту возврата функции, поэтому указатель ReceivedMessage *
, получаемый вызывающим кодом, является недопустимым, и было бы неопределенным поведение для разыменования, чтоуказатель и используйте его.
Существует несколько исправлений этой проблемы:
Первый вариант - вместо возврата указателя (ReceivedMessage *
), просто вернуть ReceivedMessage
по значению.
ReceivedMessage foo()
{
ReceivedMessage a(123);
return a;
}
Это должно работать до тех пор, пока для ReceivedMessage
.
определен правильный конструктор копирования или перемещения (неявно или иным образом). Второй вариант - использоватьstd::unique_ptr
, и вместо этого сделайте так, чтобы ваша функция возвращала std::unique_ptr<ReceivedMessage>
.
#include <memory>
std::unique_ptr<ReceivedMessage> foo()
{
std::unique_ptr<ReceivedMessage> a;
if (vals.empty()) {
a = std::make_unique<ReceivedMessage>(sc, type);
} else {
a = std::make_unique<ReceivedMessage>(sc, type, vals);
}
return a;
}
Преимущество этого подхода в том, что unique_ptr
обнуляем, поэтому вы можете создать ноль unique_ptr
без необходимости создаватьReceivedMessage
прямо сейчас.Кроме того, вы можете безопасно перемещать и назначать значения unique_ptr
, не указав правильный operator=
или правильный конструктор копирования / перемещения.
Код вызова может выглядеть следующим образом при использовании unique_ptr
:
std::unique_ptr<ReceivedMessage> message = foo();
foo->bar();
в противоположность следующему при использовании ReceivedMessage
напрямую:
ReceivedMessage message = foo();
foo.bar();