Другие языки программирования и технологии
C++: в чем принципиальная разница между использованием членов класса и указателей на них?
В чем вообще разница между объектом и указателем на объект (например, int n и int * n) я понимаю... Но вопрос вот в чем: допустим есть некий класс CFoo. Какие плюсы и минусы имеет объявление CFoo bar и CFoo * bar? Просто иногда в примерах и уроках используют ссылку на объект, притом сама ссылка никуда не передается как параметр и, вроде как, не так и нужна... Так в чем же поинт? Почему не используется просто CFoo bar?Заранее спасибо!p.s. надеюсь, мой вопрос не такой избитый, как ключи к фотошопу и ссылка на скачку каспера )))
Для класса объявление CFoo bar означает, что в это месте создается объект этого класса. Он будет занимать объем памяти необходимый этому объекту, кроме это вызывается конструктор при создании этого объекта, и деструктор при его удалении. Доступ к членам класса через оператор .
void func(BOOL bUseBar)
{
// Здесь объекта нет
if (bUseBar)
{
// Здесь в стэке выделяется память по объект Bar и вызывается конструктор класса
CFoo Bar;
Bar.Show();
// Здесь (при выходе за пределы области видимости Bar) вызывается деструктор класса
}
else
{
// Здесь никаким объектом не пахнет
}
}
CFoo *pBar; // это просто объявление указателя на объект, т. е. адрес этого объекта.
CFoo &rBar = Bar; // это просто объявление ссылки на объект, т. е. тоже адрес этого объекта. Но, в отличии от указателя, ссылка может быть создана только для уже существующего объекта. Просто написать CFoo &rBar; не получиться, компилятор спросит, а чем инициализировать ссылку?
pBar->Show(); // Вызов члена класса
rBar.Show(); // Аналогично
CFoo *pBar; не создает объекта. Чтобы указатель использовать, его нужно инициализировать, т. е. в переменной должен быть адрес объекта, а не незвестно что. Этот адрес может быть получен извне, как параметр функции, например. Или самостоятельно позаботиться о его создании
CFoo *pBar = new CFoo; // оператор new создает объект (выделяет память под объект, и уже не в стеке) , вызывает конструктор, и возвращает указатель на объект
// ...
// А после позаботиться об удалении этого объекта
delete pBar; // вызывается деструктор и выделенная память освобождается
void func(BOOL bUseBar)
{
// Здесь объекта нет
if (bUseBar)
{
// Здесь в стэке выделяется память по объект Bar и вызывается конструктор класса
CFoo Bar;
Bar.Show();
// Здесь (при выходе за пределы области видимости Bar) вызывается деструктор класса
}
else
{
// Здесь никаким объектом не пахнет
}
}
CFoo *pBar; // это просто объявление указателя на объект, т. е. адрес этого объекта.
CFoo &rBar = Bar; // это просто объявление ссылки на объект, т. е. тоже адрес этого объекта. Но, в отличии от указателя, ссылка может быть создана только для уже существующего объекта. Просто написать CFoo &rBar; не получиться, компилятор спросит, а чем инициализировать ссылку?
pBar->Show(); // Вызов члена класса
rBar.Show(); // Аналогично
CFoo *pBar; не создает объекта. Чтобы указатель использовать, его нужно инициализировать, т. е. в переменной должен быть адрес объекта, а не незвестно что. Этот адрес может быть получен извне, как параметр функции, например. Или самостоятельно позаботиться о его создании
CFoo *pBar = new CFoo; // оператор new создает объект (выделяет память под объект, и уже не в стеке) , вызывает конструктор, и возвращает указатель на объект
// ...
// А после позаботиться об удалении этого объекта
delete pBar; // вызывается деструктор и выделенная память освобождается
Несколько моментов:
1. При передаче в функцию. Если передавать объект по значению, то будет происходить его копирование внутри функции, а если по ссылке или по указателю - то копирования не будет.
2. Объект, созданный как CFoo obj; будет иметь область видимости, ограниченную блоком, в котором он создан. Можно его создать так: CFoo* ptr = new CFoo; В этом случае объект будет существовать до тех пор пока его явно не прибьют через delete.
3. Самое главное. Указателю на базовый класс можно присваивать адрес объекта производного класса и дергать по нему виртуальные функции. Именно для этого в основном и используются указатели и ссылки.
class DFoo : public CFoo { };
class DFoo1 : public CFoo{ };
CFoo* ptr = new DFoo;
...
delete ptr;
ptr = new DFoo1;
...
1. При передаче в функцию. Если передавать объект по значению, то будет происходить его копирование внутри функции, а если по ссылке или по указателю - то копирования не будет.
2. Объект, созданный как CFoo obj; будет иметь область видимости, ограниченную блоком, в котором он создан. Можно его создать так: CFoo* ptr = new CFoo; В этом случае объект будет существовать до тех пор пока его явно не прибьют через delete.
3. Самое главное. Указателю на базовый класс можно присваивать адрес объекта производного класса и дергать по нему виртуальные функции. Именно для этого в основном и используются указатели и ссылки.
class DFoo : public CFoo { };
class DFoo1 : public CFoo{ };
CFoo* ptr = new DFoo;
...
delete ptr;
ptr = new DFoo1;
...
int A;
int *B;
A это переменная то есть обект расположеный в адресном пространстве стыка
а B это указатель на обект.... то есть в этом месте стыка расположен только адрес где находятся сами данные... .
указатель можут указывать куда угодно в адресном пространстве процесса... .
размер указателя в 32 битной системе равен 32 битам ну и 64 в 64битной сответствино;
sizeof(B)=4; в 1 байте 8 бит 4*8=32
да кстати для использования указателя для хранения обекта необходимо ещё выдильть память под обект :-))))
допустим так
unsigned char Buffer[0xFF];
так мы видилили 256 байт в стыке
или так
unsigned char *Buffer;
Buffer=LocalAlloc(LPTR,1024*1024);
а так мы выделили 1МБ под буфер
используя api функцию LocalAlloc
int *B;
A это переменная то есть обект расположеный в адресном пространстве стыка
а B это указатель на обект.... то есть в этом месте стыка расположен только адрес где находятся сами данные... .
указатель можут указывать куда угодно в адресном пространстве процесса... .
размер указателя в 32 битной системе равен 32 битам ну и 64 в 64битной сответствино;
sizeof(B)=4; в 1 байте 8 бит 4*8=32
да кстати для использования указателя для хранения обекта необходимо ещё выдильть память под обект :-))))
допустим так
unsigned char Buffer[0xFF];
так мы видилили 256 байт в стыке
или так
unsigned char *Buffer;
Buffer=LocalAlloc(LPTR,1024*1024);
а так мы выделили 1МБ под буфер
используя api функцию LocalAlloc
Андрей Козырь
Спасибо!
Похожие вопросы
- Помогите найти ответ Что такое открытые (public) члены класса, и в чем заключаются особенности их использования?
- С точки зрения NFC reader-ов есть ли разница при использовании карты с NFC и
- Зачем выносить определение тел функций-членов класса в отдельный *.сpp файл?
- C++ Объясните пож. на доступном языке про спецификаторы класса памяти. В инете и в книгах слишком заумно. Продолж ниже.
- Что такое "член класса" (ООП), зачем нужны и какие бывают виды
- Список с использованием указателей на Си
- Как разыменовать указатель в C++
- [C++] Зачем делают указатель на класс?
- Зачем в С/C++ создан отдельный тип "указатель"
- Когда стоит использовать указатели c++