class SomeClass {
public:
SomeClass(const std::string & name)
: obj_name(name)
{
std::cout << "object \"" << obj_name.c_str() << "\" created" << std::endl;
}
~SomeClass()
{
std::cout << "object \"" << obj_name.c_str() << "\" destroyed" << std::endl;
}
private:
std::string obj_name;
};
SomeClass get_some_class_heap() {
return *(new SomeClass("HeapObjectFromFunc"));
}
SomeClass get_some_class_val() {
return SomeClass("ValueObjFromFunc");
}
void test_const_ref_func() { const SomeClass & value_obj_from_func_ref(get_some_class_val()); // 1
const SomeClass & heap_obj_from_func_ref(get_some_class_heap()); // 2
const SomeClass & heap_obj_ref(*(new SomeClass("HeapObj"))); // 3 //
std::cout << "end of const_ref_func()" << std::endl;
}
int main(int argc, char *argv[])
{
test_const_ref_func();
}
Получаем вот такой вот вывод:
object "HeapObjectFromFunc" created
object "ValueObjFromFunc" created
object "HeapObj" created
end of const_ref_func()
object "ValueObjFromFunc" destroyed
object "HeapObjectFromFunc" destroyed
Первый случай - все понятно: константная ссылка получает временный value-объект и "держит" его, не давая ему умереть, пока сама не выйдет за пределы области видимости функции test_const_ref_func(). Второй случай - то же самое, но возвращается ссылка не на value-объект, а на объект, созданный в куче. Казалось бы - вот они, умные указатели! Но... см.третий случай.
Третий случай - умный указатель получает ссылку на тут же динамически созданный объект. Разумеется, он не удаляет объект после того, как выходит за пределы видимости. Если бы было иначе - отладка программ на C++ была бы еще более непредсказуемой и сложной задачей, чем даже сейчас. И, кстати, поведение компилятора в этом плане во втором случае тоже вызывает много вопросов.
Во втором случае нет ничего странного.
ОтветитьУдалитьТо, что у вас:
SomeClass get_some_class_heap() - вызывает конструктор копирования, затем создает и возвращает временный объект. Константная ссылка в свою очередь "продляет" жизнь этого объекта до конца блока void test_const_ref_func().
Должно быть:
SomeClass& get_some_class_heap() - возвращет ссылку на heap-объект. Heap-объект не является временным объектом, константная ссылка никак не меняет время его жизни.
Во втором случае у вас утечка памяти.
Небольшое уточнение. В варианте приведенном мной SomeClass& get_some_class_heap() константная ссылка не влияет на время жизни объекта не только потому, что это heap-объект, но и потому, что инициализация происходит ссылкой, а не объектом.
ОтветитьУдалить