Об'єкт C ++ без нового


78

це справді просте запитання, але я роками не робив належним чином c ++, тому мене це трохи бентежить. Крім того, це не найпростіше (принаймні для мене) шукати в Інтернеті, а не намагатися.

Чому тут не використовується newключове слово та як воно працює?

В основному, що тут відбувається?

CPlayer newPlayer = CPlayer(position, attacker);

Відповіді:


67

Цей вираз:

CPlayer(position, attacker)

створює тимчасовий об'єкт типу CPlayerза допомогою вищезазначеного конструктора, а потім:

CPlayer newPlayer =...;

Згаданий тимчасовий об'єкт копіюється за допомогою конструктора копіювання до newPlayer. Кращий спосіб - написати наступне, щоб уникнути тимчасових подій:

CPlayer newPlayer(position, attacker);

7
Насправді компілятор, ймовірно, оптимізує його. У цьому випадку конструктор копіювання не буде викликаний. stackoverflow.com/questions/1758142 / ...
BostonLogan

5
Присвоєння в оголошенні не є менш ефективним, ніж використання синтаксису конструктора. Якби це були окремі висловлювання, тоді зауваження щодо тимчасових виробників було б правильним. Суть полягає в тому, що це оголошує CPlayer (як правило, у стеці), а не виділяє для нього простір із вільного сховища (купи).
Адріан Маккарті

1
Ні, майже за визначенням: Об’єкти у стеку живуть лише тоді, коли вони перебувають у зоні дії. stackoverflow.com/search?q=%5Bc%2B%2B%5D+stack+heap
Джош Лі

1
Я не думаю, що ця відповідь є точно правильною. Код OP здається тимчасовим, а потім копіює його, але стандарт 12.1.11 передбачає інше. Це просто звичайний виклик конструктора, який виявив jleedev.
Michael Kristofik

9
Компілятор вирішує, видаляти копії чи ні (у ситуаціях, коли це дозволено). 12,8 / 15.
Steve Jessop

57

Вищезазначене створює об’єкт CPlayer у стеку, отже, йому це не потрібно new. Вам потрібно використовувати лише newякщо ви намагаєтесь виділити об'єкт CPlayer у купі. Якщо ви використовуєте розподіл купи, код буде виглядати так:

CPlayer *newPlayer = new CPlayer(position, attacker);

Зверніть увагу, що в цьому випадку ми використовуємо вказівник на об’єкт CPlayer, який потрібно буде очистити за допомогою відповідного виклику delete. Об'єкт, виділений у стеку, буде автоматично знищений, коли він вийде за межі області дії.

Насправді було б простіше і зрозуміліше написати:

CPlayer newPlayer(position, attacker);

Багато компіляторів в будь-якому випадку оптимізують версію, яку ви опублікували до вищезгаданої, і її зрозуміліше читати.


2
Я вважаю, що це не правильно: "Об'єкт, виділений у купі, буде автоматично знищений, коли він вийде за межі обсягу."
Валентин

1
Ви праві, я мав на увазі писати "стек", а не "купа". Дякуємо, що вказали на це.
Timo Geusch

Погодьтеся з цим. Ми повинні зберігати код С ++ в тому ж стилі, що і код С. Так CPlayer newPlayer(position, attacker);краще, ніж CPlayer newPlayer = CPlayer(position, attacker);якщо ви хочете створити змінну стека.
tonga

10
CPlayer newPlayer = CPlayer(position, attacker);

Цей рядок створює новий локальний об'єкт типу CPlayer. Незважаючи на функціональний вигляд, це просто викликає конструктор CPlayer. Жоден тимчасовий або копіюючий процес. Об'єкт з іменем newPlayer діє до тих пір, поки в нього вкладено область дії. Ви не використовуєте newтут ключове слово, оскільки C ++ не є Java.

CPlayer* newPlayer = new CPlayer(position, attacker);

Цей рядок створює об'єкт CPlayer на купі та визначає вказівник з ім'ям newPlayer, щоб вказувати на нього. Об'єкт живе до тих пір, поки хтось deleteйого не перебере .


3
"Жоден тимчасовий або копіюючий задіяний" - Це не зовсім так. Такої гарантії немає. Але кожен гідний компілятор повинен видалити копію.
sellibitze

6

newPlayer - це не динамічно розподілена змінна, а автоматична змінна, виділена стеком:

CPlayer* newPlayer = new CPlayer(pos, attacker);

відрізняється від

CPlayer newPlayer = CPlayer(pos, attacker);

newPlayer виділяється в стеці за допомогою звичайного виклику конструктора CPlayer (позиція, зловмисник), хоча дещо детально, ніж звичайний

CPlayer newPlayer(pos, attacker);

Це в основному те саме, що сказати:

int i = int(3);

2
Тут обережно. Це "ініціалізація копіювання". Це не доручення.
sellibitze

Я стою виправлений, це не доручення; навіть конструктор копіювання не бере участі. Відповідно відредагуйте відповідь.
digitalarbeiter

2
Звичайно, копір ctor (принаймні логічно) задіяний. Ви помітите, що якщо ви зробите свою копію ctor приватною. Потім ініціалізація цієї копії більше не працюватиме. Стандарт C ++ вимагає доступного ctor копії, навіть якщо компілятор може оптимізувати копію.
sellibitze

ні, нові розподіли в купі, ваш другий гравець знаходиться в стосі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.