Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Как распределяет память конструктор копирования


Автор: AlanG 12.6.2006, 12:20
Всем доброго времени суток smile 
Меня интересует как происходит распределения памяти при создании копии объекта.
Имеем класс который содержит конструктор копирования. Как извесно, он распределяет НОВУЮ память для созданного объекта. Вот только не понятно ГДЕ и КАК он это делае? И еще, если в классе имеем оператор new который тоже распрелеляет память, какая тогда будет связь между памятью от конструктора непосредственно и памятью от оператора new ?

Пример:

Код

#include<iostream>
#include<new>
#include<cstdlib>
using mamespace std;

//***///***

calss array {
 int *p;
 int size;

 //Конструктор  
 array(int sz){
   try{ p=new int[sz]; 
 } catch(bad_alloc xa){
   cout<< "Pisez"\n;
   exit(EXIT_FAILURE); 
 }
  size=sz; //Получить значение от созданного объекта (a) 

 //Конструктор копирования
 array (const array &a){
   try{ p=new int[a.size]; 
      }catch(bad_alloc xa){
   cout<< "Pisez"\n;
   exit(EXIT_FAILURE); 
      } 
    }
 };

void main(){
 array a(11); //Создается объект
                    //Вызывается констрктор   
 array a2_copia(a); //Вызов конструктора копирования 

}


 

Автор: Earnest 12.6.2006, 12:30
Цитата(AlanG @  12.6.2006,  13:20 Найти цитируемый пост)
 Как извесно, он распределяет НОВУЮ память для созданного объекта

Не "как известно", а "как напишешь".
Конструкторы не распределяют память. 
Они инициализируют объект в той памяти, которую им дали. 
В твоем примере оба объекта создаются на стеке.
Если ты в своей реализации конструктора выделяешь память оператором new, то это частный случай. Память выделяется всегда в куче (если ты используешь стандартный new). Никакой связи с тем, какую память получил конструктор, нет. Т.е. как бы ни был создан объект array (как глобальная переменная, как автоматический объект или динамически, через new) - внутренний new будет выделять память одинаково.
 

Автор: AlanG 12.6.2006, 12:41
Цитата

Конструкторы не распределяют память. 

Я наверное НЕдописал кое что smile 
Конструкторы копирования, как раз таки распределяют память, для этого они и предусмотрены. Если конструктор копирования ЯВНО не реализован в програме, используется конструктор по умоляанию, но с ним пробдлема, при вызове деструктора, удаляется память каждого из созданных объектов (естественно из этого же класса). Когда создается новый объект (точнее копия объекта а), в данном случае он создается при создании нового объекта a2_copia. (еще может создаватся при вызове функций с передачей объекта). Копия создается именно в тот момент, когда передается параметр в виде объекта. Собствено вопрос: ГДЕ и КАК распределяется память для ЭТОЙ копии (копии объекта а)?

Добавлено @ 12:42 
Про new я зря упомянул, только запутал..... 

Автор: Daevaorn 12.6.2006, 12:49
Цитата(AlanG @  12.6.2006,  13:41 Найти цитируемый пост)
Конструкторы копирования, как раз таки распределяют память, для этого они и предусмотрены

Ложь!
Код

array (const array &a)

Сама сигнатура его говорит о том, что он работает уже с выделенной памятью под объекты( что уже сказала Earnest ). 
Цитата(AlanG @  12.6.2006,  13:41 Найти цитируемый пост)
 ГДЕ и КАК распределяется память для ЭТОЙ копии (копии объекта а)?

На стеке, ты сам это написал:
Код

array a2_copia(a); 

 

Автор: MAKCim 12.6.2006, 12:52
когда компилятор встречает вызов конструктора копирования для объекта, который будет размещен в стеке
то скорее всего просто уменьшается указатель стека на sizeof(<структура, представляющая данные объекта класса>) ,байт и call-ом вызывается процедура, соответствующая конструктору копирования (или сгенерированному КК) и туда передается указатель на первый байт данных объекта (текущий (измененный) указатель стека). Собственно эта процедура и инициализирует поля объекта (то есть не занимается выделением памяти а работает уже с существующими адресами)
  

Автор: AlanG 12.6.2006, 13:04
Цитата

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

Тогда я наверное чего то недопонял... Хорошо, а что происходит когда я передаю объект в качестве параметра, другой функции?
Код

void main(){
 array a(11); //Создается объект
                     //Вызывается констрктор   
 func1(a);  //Передача объекта (передается копия, для которой, конструктор  распределяет НОВУЮ память)
}

 func1(array a1) {
 cout<<a1.size;
 }
 

Автор: Earnest 12.6.2006, 13:05
Цитата(AlanG @  12.6.2006,  13:41 Найти цитируемый пост)
при вызове деструктора, удаляется память каждого из созданных объектов 

Это тоже не так. Распределение\освобождение памяти и конструирование\разрушение объекта - это два разных процесса, никак не связанных. Т.е. только на вид они связаны.
Выделение\освобождение памяти - это new\delete. При вызове деструктора память не удаляется. Когда ты пишешь MyClass* pa = new MyClass(аргументы); то сначала выделяется память (оператором new), а потом эта память передается конструктору для инициализации. Если объект размещается на стеке, то память не выделяется, а просто, как написал MAKCim, текущий указатель стека смещается на размер объекта, а предыдущий передается конструктору для инициализации (что-то типа placement new). Собственно, сам механизм placement new - это способ вызвать конструктор в нужной области памяти.
Инициализация - это, грубо говоря, присваивание начальных значений данным и, в случае полиморфных классов, присваивание нужного адреса таблице виртуальных ф-й (возможно не одной). Деструктор ... да, в общем, может ничего не делать. Разве что подменяет \ очищает адрес vtable...  

Автор: Daevaorn 12.6.2006, 13:11
Цитата(AlanG @  12.6.2006,  14:04 Найти цитируемый пост)
func1(array a1)

В данном случае объект-параметр a1 будет создан на стеке, т.к. передается по значению. 

Автор: MAKCim 12.6.2006, 21:07
Цитата

Хорошо, а что происходит когда я передаю объект в качестве параметра, другой функции?

1. Изменение указателя стека на размер объекта
2. Передача нужного адреса через стек в процедуру которая соответствует конструктору копий
3. Инициализация полей в этой процедуре
4. Вызов нужной функции (при этом объект будет находится по текущему указаателю стека + 4 байта (на 32 разрядных платформах)) 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)