"новый" оператор в С++, указательный вопрос
Тупой вопрос, но всякий раз, когда вы вызываете новое, у вас всегда есть указатель?
SomeClass *person = new SomeClass();
И это потому, что вам нужен указатель, указывающий на это новое пространство памяти, которое было выделено для человека переменной SomeClass? Спасибо!
Ответы
Ответ 1
Если new
завершается успешно, он всегда возвращает указатель (если он не завершается успешно, генерируется исключение, и ничего не возвращается).
Указатель относится к объекту, который был создан, или в случае с массивом, указателю на первый элемент массива.
Ответ 2
Да, всегда указатель. Даже если вы хотите перегрузить новый, тип возврата должен быть void *.
И вы правы с целью
Ответ 3
new создает объект в куче, и все, что он может вернуть, это его адрес - указатель.
Ответ 4
Да. Если вы спрашиваете, почему он не возвращает ссылку вместо этого, поскольку ссылки лучше, чем указатели, ответ - историческое наследие.
Когда С++ находилась в разработке, если машине не удалось получить память для объекта, был возвращен специальный указатель NULL
. Вот как это делается в C:
SomeClass *person;
person = (SomeClass*) malloc( sizeof( SomeClass ) );
if ( person == NULL ) fprintf( stderr, "no more people allowed!" );
В стандартном С++ ошибки возвращаются вместо исключения:
try {
SomeClass *person = new SomeClass;
// do something
} catch ( std::bad_alloc ) {
std::cerr << "no more people!" << std::endl;
} catch ( ... ) {
// using exceptions allows for other errors
// from inside SomeClass::SomeClass too
}
Вы все еще можете сделать это старомодным способом, но с nothrow
:
SomeClass *person = new( std::nothrow ) SomeClass;
if ( person == NULL ) std::cerr << "no more people allowed!" << std::endl;
Результат: это вполне разумный и хороший стиль:
SomeClass &person = * new SomeClass; // don't need no stinkin pointers!
Ответ 5
Новое выражение возвращает указатель, но вы можете использовать его с классами "умного указателя" (например, из Boost). Итак:
boost::shared_ptr<SomePerson> person(new SomePerson);
Я должен также указать, что, хотя вы можете использовать круглые скобки, если вы исходите из фона Java, в С++, круглые скобки не нужны при использовании конструктора по умолчанию. Так, например, обычно при записи по умолчанию new T
записывается new T
, но при написании объекта с использованием конструктора, отличного от значения по умолчанию, записывается new T(param)
или new T(param1,...,paramN)
.
Да, это правильно; теоретически можно написать (новый SomePerson) → doSomething(), но это будет утечка памяти; С++ не содержит сборку мусора, поэтому необходимо сохранить результат нового выражения в чем-либо (указатель или интеллектуальный указатель), чтобы его можно было правильно освободить.