2013-12-06 3 views
1

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

Пример (C#):

List<Person> names = new List<Person>(); 

Person friend = null; 
for(int i = 0; i < 5; i++) 
{ 
    friend = new Person(); 
    Person guy = new Person(); 

    guy.name = "Bob" + i; 
    friend.name = "Bill" + i; 

    names.Add(guy); 
    names.Add(friend); 
} 

Здесь у меня есть два объекта Person, используемые в том же цикле, чтобы сэкономить пространство.

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

Принимая во внимание, что каждому новому «парному» объекту присваивается новое место памяти.

При условии, что это правильно, и, пожалуйста, исправьте меня, если это неправильно, это означает, что использование «друга» над «парнем» более эффективно с точки зрения памяти.

Был ли когда-нибудь случай, когда «парень» был бы лучше? Может ли это зависеть от реализации конструктора?

ответ

9

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

Нет, это не тот случай. Вы перезаписываете предыдущее значение в переменной - но это не объект. Это всего лишь ссылка на объект. Есть еще одна ссылка на объект в списке. Сам объект не будет перезаписан вообще. Каждый создаваемый вами объект не зависит от других.

С точки зрения разницы между объявлением переменной внутри цикла или вне цикла, это не имеет большого значения. Есть несколько отличий:

  • Если он объявлен вне цикла, вы можете использовать переменную внутри цикла, прежде чем присваивать новое значение к нему, так что вы получите, чтобы увидеть предыдущее значение
  • Если он объявлен вне цикл, вы также можете использовать переменную после цикла, чтобы прочитать последнее назначенное значение
  • Если оно объявлено вне цикла, и вы используете анонимную функцию внутри цикла, то каждая анонимная функция будет захватывать той же переменной. Если он находится внутри цикла, каждая анонимная функция будет захватывать другую переменную. Если все это звучит как gobbledygook для вас в данный момент, вы можете, вероятно, проигнорировать его
  • Если он объявлен внутри цикла, то в отдельном блоке вы можете объявить отдельную переменную с тем же именем; вы не можете этого сделать, если объявлено вне цикла.

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

+0

Спасибо за это. Действительно отличное объяснение. Нет, я это понимаю, это была одна из тех вещей, в которых я никогда не обнимал голову. Еще раз спасибо! – tjheslin1

0

Когда вы создаете нового друга, вы не используете повторное использование ячейки памяти. Вы создаете новый объект и присваиваете его адресу переменной friend. Таким образом, вы «забываете» о предыдущем знакомом.

Таким образом, эффективность памяти невелика. И если вы не используете цикл friend for for, то также проще определить переменную друга внутри так же, как вы с парнем.

+0

я вижу. Спасибо за ввод. – tjheslin1

0

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

Это понимание неправильное. Вы нарушаете соединение от переменной friend к объекту в памяти, но этот прежний объект в памяти все еще жив. Если нет других ссылок на этот объект, то для коллекции будет , но нет никакой гарантии, когда коллекция будет проходить. В этом случае у вас все еще есть существующие ссылки на старый объект (через коллекцию имен), и поэтому единственное отличие вашего кода в том, что последний объект, созданный и назначенный переменной friend, по-прежнему будет доступен после цикла.

2

В чем разница между созданием объекта внутри и снаружи цикла?

Нет, вы создаете новые объекты Person внутри цикла в обоих случаях. Вы просто создаете одну переменную внутри цикла и одну переменную снаружи. Единственное различие между этими двумя заключается в том, что после завершения цикла friend по-прежнему содержит ссылку на последний экземпляр, который вы назначили ему внутри цикла.

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

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

Как только все ссылки на экземпляр удаляются, garbage collector может освободить память, связанную с этим старым экземпляром, что позволяет повторно использовать эту память позже. Но здесь вы добавляете каждый экземпляр в список, поэтому они не будут собраны до тех пор, пока список names не будет удален или уничтожен (и любые другие экземпляры, которые могут существовать в другом месте).

+0

Очень полезно! Определенно помог мне понять. ура – tjheslin1