Вопрос о стековом фрейме: Java по сравнению с C++

Artima опубликовал интервью с одним из архитекторов.NET, Anders Hejlsberg, который остро страхует аргументы от контролируемых исключительных ситуаций. Короткий дегустатор:

пункт бросков, по крайней мере, способ, которым это реализовано в Java, не обязательно вынуждает Вас обработать исключения, но если Вы не обрабатываете их, он вынуждает Вас подтвердить точно, через который могли бы пройти исключения. Это требует, чтобы Вы или поймали объявленные исключительные ситуации или поместили их в Ваш собственный пункт бросков. Для работы вокруг этого требования люди делают смешные вещи. Например, они украшают каждый метод, "выдает Исключение". Это просто полностью побеждает функцию, и Вы просто заставили программиста записать больше gobbledy месива. Это не помогает никому.

7
задан pankajt 26 August 2009 в 18:33
поделиться

5 ответов

Это несколько упрощено, но в основном точно, насколько мне известно.

В Java все объекты размещаются в куче (включая все ваши переменные-члены). Большинство других вещей (параметров) являются ссылками, а сами ссылки хранятся в стеке вместе с собственными типами (целые числа, длинные числа и т. Д.), За исключением строки, которая является скорее объектом, чем собственным типом.

В C ++, если вы было бы выделить все объекты с помощью ключевого слова «new», это будет примерно такая же ситуация, как и в java, но есть один уникальный случай в C ++, потому что вместо этого вы можете размещать объекты в стеке (вам не всегда нужно использовать «new» ").

Также обратите внимание, что производительность кучи Java ближе к производительности стека C, чем производительность кучи C, сборщик мусора делает довольно умные вещи. Это' s по-прежнему не так хорош, как стек, но намного лучше, чем куча. Это необходимо, поскольку Java не может размещать объекты в стеке.

6
ответ дан 6 December 2019 в 23:11
поделиться

В C ++ объекты могут быть размещены в стеке ... например, localObj в вашем главном Q3

Я чувствую некоторую путаницу в отношении классов и экземпляров. «MyInstance» имеет больше смысла как имя переменной, чем как имя класса. В вашем примере Q1 «число» присутствует в каждом объекте типа MyInstance. «счетчик» используется всеми экземплярами. «MyInstance :: counter = 100» является допустимым назначением, а «MyInstance :: number = 100» - нет, поскольку вы не указали какому объекту должен быть присвоен член "номер".

1
ответ дан 6 December 2019 в 23:11
поделиться

Q1. В Java все объекты, массивы и переменные класса хранятся в куча? Верно ли то же самое и для C ++? Является сегмент данных является частью кучи?

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

Единственное время, когда объекты находятся в куче, - это если вы используете ключевое слово new или что-то из malloc семейство функций

Q2. Насколько я понимаю, переменные, которым заданы определенные значения компилятором хранятся в данных сегмент и неинициализированные глобальные и статические переменные хранятся в BSS (Блок начинается с символа). В этом случай, MyInstance :: counter статичен инициализируется нулем компилятором и поэтому он хранится в BSS и MyInstance :: число, которое инициализировано до 100, сохраняется в сегмент данных. Правильно ли я сделал вывод?

Да, вы правильно понимаете раздел BSS. Однако, поскольку число не является статическим, код:

MyInstance::number = 100;

недопустим, его необходимо либо сделать статическим, либо правильно инициализировать в конструкторе. Если вы инициализируете его в конструкторе, он будет существовать везде, где размещен объект-владелец. Если вы сделаете его статическим, он окажется в разделе данных ... если где-нибудь. Часто переменные static const int могут быть встроены непосредственно в используемый код, так что глобальная переменная вообще не нужна.

Q3. Рассмотрим следующий фрагмент кода: ...

void doHello (MyInstance & localObj) {

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

void doHelloAgain (MyInstance localObj) {

копия переданного параметра помещается в стек.

MyInstance localObj;
// 3.3 Where is this stored in heap or stack?

localObj - это в стеке.

1
ответ дан 6 December 2019 в 23:11
поделиться

Все области памяти в C ++ перечислены здесь

1
ответ дан 6 December 2019 в 23:11
поделиться

Q1

Java также хранит переменные в стеке, но экземпляры классов размещаются в куче. В C ++ вы можете размещать экземпляры своих классов либо в стеке, либо в куче. Используя ключевое слово new , вы выделяете экземпляр в куче.

Сегмент данных не является частью кучи, но выделяется при запуске процесса. Куча используется для распределения динамической памяти, в то время как сегмент данных является статическим, а его содержимое известно во время компиляции.

Сегмент BSS - это просто оптимизация, при которой все данные принадлежат сегменту данных (например, строка, постоянные числа и т. Д.) ), которые не инициализированы или не инициализированы нулем, перемещаются в сегмент BSS. Сегмент данных должен быть встроен в исполняемый файл, и, переместив «все нули» в конец, они могут быть удалены из исполняемого файла. Когда исполняемый файл загружается, сегмент BSS выделяется и инициализируется нулем, и компилятор все еще может знать адреса различных буферов, переменных и т. Д. Внутри сегмента BSS.

Q2

MyClass :: number хранится там, где выделен экземпляр класса MyClass . Это может быть как в куче, так и в стеке. Обратите внимание в третьем квартале, как a указывает на экземпляр MyClass , выделенный в куче, а localObj размещен в стеке. Таким образом, a-> number находится в куче, а localObj.number - в стеке.

Поскольку MyClass :: number является переменной экземпляра вы не можете назначить его так:

MyClass::number = 100;

Однако вы можете назначить MyClass :: counter , поскольку он статичен (за исключением того, что он частный):

MyClass::counter = 100;

Q3

Когда вы вызываете doHello переменную localObj main ]) передается по ссылке. Переменная localObj в doHello ссылается на эту переменную в стеке. Если вы его измените, изменения будут сохранены в стеке, где размещается localObj в main .

Когда вы вызываете doHelloAgain переменную localObj main ) копируется в стек. Внутри doHelloAgain переменная localObj размещена в стеке и существует только на время вызова.

MyClass::counter = 100;

Q3

Когда вы вызываете doHello , переменная localObj main ) передается по ссылке. Переменная localObj в doHello ссылается на эту переменную в стеке. Если вы его измените, изменения будут сохранены в стеке, где размещается localObj в main .

Когда вы вызываете doHelloAgain переменную localObj main ) копируется в стек. Внутри doHelloAgain переменная localObj размещена в стеке и существует только на время вызова.

MyClass::counter = 100;

Q3

Когда вы вызываете doHello , переменная localObj main ) передается по ссылке. Переменная localObj в doHello ссылается на эту переменную в стеке. Если вы его измените, изменения будут сохранены в стеке, где размещается localObj в main .

Когда вы вызываете doHelloAgain переменную localObj main ) копируется в стек. Внутри doHelloAgain переменная localObj размещена в стеке и существует только на время вызова.

Если вы его измените, изменения будут сохранены в стеке, где размещается localObj в main .

Когда вы вызываете doHelloAgain переменную localObj main ) копируется в стек. Внутри doHelloAgain переменная localObj размещена в стеке и существует только на время вызова.

Если вы его измените, изменения будут сохранены в стеке, где размещается localObj в main .

Когда вы вызываете doHelloAgain переменную localObj main ) копируется в стек. Внутри doHelloAgain переменная localObj размещена в стеке и существует только на время вызова.

2
ответ дан 6 December 2019 в 23:11
поделиться