2012-02-15 4 views
7

Когда я хочу создать экземпляр класса в C++, я обычно хожу такC++ указателя и ссылки с новым ключевым словом при инстанцировании

Book bk = new Book(); 

Моего профессор недавно сделал это

Book &bk = *new Book(); 

Он только сказал мне, что он использовал бы ссылку, чтобы иметь возможность использовать точку (например, bk.getTitle();) вместо стрелки (например, bk-> getTitle();). Я понимаю эту часть кода, но что происходит, когда вы используете оператор * в сочетании с новым?

Заранее спасибо

полный пример кода можно найти here это arraystack в основной функции

+7

Итак, ваш профессор показал вам, как утечка памяти, здорово. – ildjarn

+2

Если ваш профессор использует этот код для чего-то другого, кроме как пример чего-то, чего вы действительно не должны делать, тогда вы должны найти нового профессора. –

+0

Возможно, ваш профессор сказал: 'const Book & bk = Book();'. Если это не так, я честно не понимаю, что имел в виду ваш профессор. – Mahesh

ответ

15

Это:

Book &bk = *new Book(); 

является в значительной степени эквивалентно следующему:

Book *p = new Book(); // Pointer to new book 
Book &bk = *p; // Reference to that book 

Но есть одно важное различие; в исходном коде у вас нет указателя, который вы можете использовать для delete динамически выделенного объекта, когда вы закончите с ним, так что вы эффективно создали утечку памяти.

Конечно, вы можете сделать это:

delete &bk; 

но это чрезвычайно не-идиоматических C++, и очень вероятно, вызовет проблемы позже.

Таким образом, нет абсолютно никаких оснований писать такой код, поэтому не делать этого. Любое из следующих условий:

Book bk; 
Book bk = Book(); 
+0

спасибо, я думаю, что я не буду его использовать. Класс больше относится к шаблонам проектирования, чем к C++, поэтому я просто проигнорирую этот стиль программирования и сделаю это по-своему. – tim

+1

Вы определенно не создали утечку памяти, хотя, я думаю, это огромное завышение –

+0

@Seth: Исходный код действительно имеет утечку ... Что вы имеете в виду? – ildjarn

0

Я нашел ситуацию, которая позволила мне задуматься об этом синтаксисе. Рассмотрим умный указатель на класс Base и который должен содержать указатель на производный класс, и вы хотели бы получить доступ к некоторым не виртуальным вещам производного класса после построения. В этом случае что-то вроде этого является законным и не может быть так плохо:

Derived & d = * new Derived(); 

d.d_method(..whatever..); 
d.d_member = ..whatever..; 
... 

std::unique_ptr<Base> p(&d); 

Наконец-то я по-прежнему предпочитает маленькие стрелки странных амперсанды:

Derived d = new Derived(); 

d->d_method(..whatever..); 
d->d_member = ..whatever..; 
... 

std::unique_ptr<Base> p(d); 

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

Другие вещи, которые приводят либо к утечкам, либо delete &d; - это просто плохо, плохо, плохо.

Смежные вопросы