С++ vs Java: объекты с бесконечным циклом создают только С++
Это был вопрос в одной из моих книг (без ответа), о котором я думал уже несколько дней. Является ли ответ просто, что код С++ в конечном итоге сбой, потому что он создает ячейку памяти для мусора после каждой итерации?
Рассмотрим следующие фрагменты кода Java и С++, части двух версий приложения на основе графического интерфейса, которое собирает пользовательские настройки и использует их для сборки команды и ее параметров. Метод /function getUserCommandSpecification() возвращает строку, представляющую код команды и ее параметры. Возвращенная строка используется для создания требуемой команды, которая затем выполняется.
Предположим следующее:
(i) После создания в цикле while объекта Command (ссылка на cmd в случае Java или указана cmd в случае С++) ссылка/указатель cmd на сгенерированный объект больше не ссылается или не используется.
(ii) Приложение также определяет команду класса вместе с ее методом/функцией execute().
а. Какая из двух версий кода, подробно описанная ниже, в конечном итоге потерпит крах.
б. Объясните, почему версия программы вылетает, а другая не сбой.
Код Java
...
while (true) {
String commandSpecification = getUserCommandSpecification();
Command cmd = new Command(commandSpecification);
cmd.execute();
}
...
Код С++
...
while (true) {
string commandSpecification = getUserCommandSpecification();
Command* cmd = new Command(commandSpecification);
cmd -> execute();
}
...
Ответы
Ответ 1
Да, версия С++ протекает из-за new Command(...)
без delete
. Конечно, его можно было бы легко кодировать по-разному, чтобы избежать этого:
...
while (true) {
string commandSpecification = getUserCommandSpecification();
Command cmd(commandSpecification);
cmd.execute();
}
...
... поэтому я не уверен, что пример такой же поучительный, как они думают.
Ответ 2
Код С++ создает бесконечное количество объектов Command
, которые никогда не удаляются. В С++ нет сборки мусора. Во всех экземплярах, созданных new
, нужно вызвать delete
.
Ответ 3
Использование исходных указателей выпадает из стиля. Здесь это необязательно, как уже указывалось. В случае, когда указатель действительно нужен, используйте std:: unique_ptr.
while (true) {
string commandSpecification = getUserCommandSpecification();
std::unique_ptr<Command> cmd(new Command(commandSpecification));
cmd -> execute();
}
Здесь нет утечки памяти.
Ответ 4
Пример С++ приведет к сбою из-за утечки памяти.
Command* cmd = new Command(commandSpecification);
непрерывно вызывается без соответствующего delete
.
Ответ 5
В С++ отсутствует сбор мусора (кроме локалей в пределах области). Таким образом, С++ постоянно выделяет объекты Command
в кучу, не освобождая эту память при вызове delete
. Таким образом, программа С++ в конечном итоге исчерпает память.
В Java сборщик мусора увидит, что объекты в куче больше не ссылаются и освобождают их, что позволяет избежать ошибки в памяти.
Ответ 6
AFAIK, в С++ вам нужно явно уничтожить созданные вами объекты (используя ключевое слово new
), в то время как в Java сборщик мусора (который помогает восстановить память, занятую объектами, которые больше недоступны) позаботится об этом для тебя.
В Java объекты, созданные таким образом, будут увеличивать частоту младших GC, поэтому эти объекты, вероятно, даже не попадут в область старого поколения в куче (в зависимости от того, как долго выполняется execute
),.
Extreme Performance с Java
Ответ 7
Так как он еще не был явно указан (поиск слова на странице не имеет совпадений), я считаю, что лучше всего добавить: этот код на С++ имеет явную утечку памяти ошибка.
Здесь еще одна рабочая альтернатива, использующая std::auto_ptr
(Boost boost::scoped_ptr
или Qt QScopedPointer
- альтернативные интеллектуальные указатели):
while (true) {
string commandSpecification = getUserCommandSpecification();
std::auto_ptr<Command> cmd(new Command(commandSpecification));
cmd->execute();
}
Ответ 8
прочитал о сборке мусора в java.
в java вам не нужно было удалять объекты вручную, потому что jvm делает это за вас автоматически, но в С++ вам нужно удалить объекты, которые вам больше не нужны.
также сборщик мусора является полнофункциональным инструментом в java, если вы хотите помочь ему, вы можете сделать ссылку объекта на null после завершения работы.
Object x=new Object()
///
.
.
.
you did your works
x=null;