Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 4.69
Alex Z
27 / 1 / 0
Регистрация: 29.06.2011
Сообщений: 136
#1

Зачем вызывается конструктор при объявлении указателя на класс - C++

21.11.2012, 18:18. Просмотров 1890. Ответов 16
Метки нет (Все метки)

Не знаю, правильно или нет назвал тему...

Вот такая ситуация понятна:
C++
1
2
int * pHeap = new int;
*pHeap = 7;
Здесь мы выделяем в динамической памяти место для хранения числа типа int. Результатом команды new будет адрес ячейки в динамической памяти. Этот адрес мы и присваиваем созданному указателю. Ну а потом по этому указателю уже можем доступаться до ячейки.

Не понятна ситуация, когда в динамической памяти размещается объект какого-то класса. Пишем по-сути так же:
C++
1
Cat *pCat = new Cat;
Цитирую учебник: "В данном случае в операторе new использован стандартный конструктор класса, т.е. конструктор, применяемый без параметров. Следует напомнить, что при создании объекта класса вызов конструктора происходит всегда, независимо от того, размещается объект в стеке или в области динамической памяти." И всё, больше никаких объяснений нет. Я что понять не могу: а зачем вообще в этом случае вызывается конструктор? Ведь конструктор вызывается при создании объекта, например:
C++
1
Cat Frisky;
Здесь создаётся объект Frisky типа (класса) Cat. Значит тут вызывается конструктор. Это понятно. А здесь то зачем конструктор?:
C++
1
Cat *pCat = new Cat;
Тут же вроде объект не создаётся. Я понимаю так: команда new Cat выделяет необходимое количество места в динамической памяти. Например, если класс Cat содержит 2 переменные типа unsigned short int (возраст и вес кота), то будет выделено 4 байта. А потом адрес присваивается указателю pCat. Непосредственно объект то вроде бы не создаётся. Я вначале думал, что может в книге опечатка, нет, по ходу я туплю...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.11.2012, 18:18
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Зачем вызывается конструктор при объявлении указателя на класс (C++):

При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О - C++
Вот такой кодclass A { public: A(){} virtual ~A(){} }; class C { public:

this(Всегда ли вызывается конструктор при не явной передачи объекта в конструктор) - C++
class Test { int i; public: void test(int i) { this -> i = i; } }; Конструктор Test::Test всегда вызывается...

Написать обработчик исключений ситуации при преобразовании указателя на класс B до указателя на абстрактный класс А ... - C++
Написать обработчик исключений ситуации при преобразовании указателя на класс B до указателя на абстрактный класс А ... как сделать...

Вылетает при объявлении указателя - C++
class pixel { public: GLint x; GLint y; int lives; int score; BADpixel *BP; pixel(); pixel(GLint, GLint, int, int...

Зачем для указателя на объект класса создается отдельный класс - C++
Читаю книгу Джефа Элджера "Библиотека программиста С++", там в главе про умные указатели приводится пример, где для указателя на класс...

Ошибка C4307 при объявлении в main() указателя шаблона-класса - C++
Привет, всем. Помогите, плиз, с синтаксисом. Возникает, ошибка при объявлении в main() указателя шаблона-класса. #include <iostream> ...

16
Croessmah
Ушел
Эксперт CЭксперт С++
13553 / 7704 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 3
Завершенные тесты: 1
21.11.2012, 18:29 #2
Цитата Сообщение от Alex Z Посмотреть сообщение
Непосредственно объект то вроде бы не создаётся.
Как не создается? Почитайте еще раз что такое классы и про оператор new.

Добавлено через 3 минуты
Для примера, сделайте конструктор с параметром и в new укажите параметры:
C++
1
Cat *pCat = new Cat(34);
1
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
21.11.2012, 18:35 #3
Цитата Сообщение от Alex Z Посмотреть сообщение
Я понимаю так: команда new Cat выделяет необходимое количество места в динамической памяти.
и вызывает конструктор. Это и есть динамическое создание объекта. А сырую память выделяют: malloc, calloc и realloc.
1
asidorchenko
379 / 205 / 25
Регистрация: 09.04.2012
Сообщений: 635
23.11.2012, 13:10 #4
Тут же вроде объект не создаётся.
Это не так. Объект создается, поэтому вызывается конструктор. Простое объявление указателя не создает объект, его создает new. До создания объекта попытки манипулировать объектом через указатель выдаст ошибку исполнения.
1
alsav22
5426 / 4821 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
23.11.2012, 16:56 #5
Цитата Сообщение от Alex Z Посмотреть сообщение
Цитирую учебник: "В данном случае в операторе new использован стандартный конструктор класса, т.е. конструктор, применяемый без параметров. Следует напомнить, что при создании объекта класса вызов конструктора происходит всегда, независимо от того, размещается объект в стеке или в области динамической памяти." И всё, больше никаких объяснений нет. Я что понять не могу: а зачем вообще в этом случае вызывается конструктор? Ведь конструктор вызывается при создании объекта
Учебник пишет, что объект создаётся и вызывается конструктор по умолчанию для инициализации объекта. Просто, в данном случае, создаётся объект без имени, доступ к которому обеспечивает указатель.

Добавлено через 4 минуты
Цитата Сообщение от Alex Z Посмотреть сообщение
Я понимаю так: команда new Cat выделяет необходимое количество места в динамической памяти. Например, если класс Cat содержит 2 переменные типа unsigned short int (возраст и вес кота), то будет выделено 4 байта. А потом адрес присваивается указателю pCat. Непосредственно объект то вроде бы не создаётся.
Именно так и создаётся объект класса, или вы создание объекта как-то по другому представляете?
1
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
24.11.2012, 19:09 #6
Цитата Сообщение от Alex Z Посмотреть сообщение
Ведь конструктор вызывается при создании объекта,
Вот именно.

Добавлено через 12 минут
Alex Z, раздели декларацию указателя и вызов конструктора, между ними поставь другую операцию и протрассируй.
C++
1
2
3
4
int a;
Cat *pCat=NULL; // Здесь создаётся указатель.
a=200;
pCat=new Cat; // А вот здесь зоздаётся объект.
И запомни, если правый операнд new - класс, то память выделяется для объекта, это и есть его создание. Объекты только так и создаются, просто иногда это прописывется сразу в декларации статического, или автоматического объекта. Разумеется, при создании объекта, конструктор должен инициировать его начальным значением.
2
Alex Z
27 / 1 / 0
Регистрация: 29.06.2011
Сообщений: 136
24.11.2012, 20:50  [ТС] #7
Цитата Сообщение от taras atavin Посмотреть сообщение
раздели декларацию указателя и вызов конструктора, между ними поставь другую операцию и протрассируй.
C++
1
2
3
4
int a;
Cat *pCat=NULL; // Здесь создаётся указатель.
a=200;
pCat=new Cat; // А вот здесь зоздаётся объект.
Да, так понятнее, спасибо.

Только единственное, слово NULL во 2-ой строчке, это то же самое, что и число 0, или чем-то отличается? Вот так можно?:
C++
1
2
3
4
int a;
Cat *pCat=0;
a=200;
pCat=new Cat;
0
alsav22
5426 / 4821 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
24.11.2012, 20:59 #8
Цитата Сообщение от Alex Z Посмотреть сообщение
это то же самое, что и число 0, или чем-то отличается?
То же самое.
1
ntny
7 / 7 / 0
Регистрация: 17.06.2012
Сообщений: 168
24.11.2012, 21:28 #9
Добавлено через 11 минут
хм туплю кстати
0
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
25.11.2012, 02:44 #10
taras atavin, new вполне может выделять сырую память, если что.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
 
struct S
{
    S() { std::cout << "C-tor" << std::endl; }
    ~S() { std::cout << "D-tor" << std::endl; }
};
 
int main()
{
    void* memory = operator new(sizeof(S));
    S* p = new (memory) S();
    p->~S();
    operator delete(memory);
}
http://ideone.com/BTVQ4p

Про корректность очистки памяти не могу сказать, ибо юзать такое приходится редко.
2
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
25.11.2012, 12:41 #11
Цитата Сообщение от Alex Z Посмотреть сообщение
Вот так можно?:
Можно, но без гарантии: NULL - это указатель в никуда, определённый, как простое целое, 0 - это именно 0. Обычно они совпадают, но не всегда, а зависит это от архитектуры, а не от языка. Например, у сигнальных процессоров 0 - вполне валидный адрес, а NULL - наоборот очень большой номер байта. Так вот, если вдруг не 0, то для NULL заменяешь дефайн и всё, а с нолём придётся этот 0 отлавливать по всей проге. А ещё лучше современный null_ptr.

Добавлено через 1 минуту
Цитата Сообщение от ForEveR Посмотреть сообщение
p->~S(); operator delete(memory);
delete сам вызывает деструктор.

Добавлено через 2 минуты
Цитата Сообщение от ForEveR Посмотреть сообщение
taras atavin, new вполне может выделять сырую память, если что.
Может. Если его по-кривому перегрузить, или указать правым операндом void. Но предназначен он не для этого.
0
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
25.11.2012, 13:00 #12
taras atavin, Почитай про operator delete. Он не вызывает деструктор.
Может. Если его по-кривому перегрузить, или указать правым операндом void. Но предназначен он не для этого.
Ой-ли? placement new, не слышал?
0
Kuzia domovenok
1947 / 1800 / 137
Регистрация: 25.03.2012
Сообщений: 6,238
Записей в блоге: 1
25.11.2012, 13:11 #13
Цитата Сообщение от ForEveR Посмотреть сообщение
Ой-ли? placement new, не слышал?
если не ошибаюсь, placement new выполняет диаметрально противоположную задачу.

Добавлено через 1 минуту
Цитата Сообщение от taras atavin Посмотреть сообщение
new вполне может выделять сырую память,
а placement new наоборот. новой памяти не выделяет, но "делает существующую несырой".
0
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
25.11.2012, 13:16 #14
Цитата Сообщение от ForEveR Посмотреть сообщение
taras atavin, Почитай про operator delete. Он не вызывает деструктор.
Так и запишем: трассировать не пробовал.
0
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
25.11.2012, 13:18 #15
Kuzia domovenok, Все верно, это меня перекосило. Впринципе я отвечал про перегрузку на тему void* вторым аргументом. Как раз перегрузка, где void* вторым аргументом есть placement-new.

C++
1
2
3
void* operator new (std::size_t size) throw (std::bad_alloc);
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw();
void* operator new (std::size_t size, void* ptr) throw();
Добавлено через 1 минуту
taras atavin, Не понял. Ты споришь с тем, что функция operator delete не вызывает деструктор объекта или с чем?
0
25.11.2012, 13:18
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.11.2012, 13:18
Привет! Вот еще темы с ответами:

Какой конструктор вызывается при value initialization объекта? - C++
Привет, есть вот такой код, например: #include &lt;iostream&gt; struct Test { int data; Test() : data(30) { std::cout &lt;&lt;...

Почему конструктор вызывается повторно при преобразовании типов? - C++
В качестве примера предлагаю рассмотреть примерчик из учебника. В примере мы создаём класс, содержащий в качестве поля строку символов и...

Почему не вызывается конструктор копирования при возврате объекта из функции - C++
Добрый день! Насколько мне известно, конструктор копирования вызывается: 1) при передачи объекта как аргумента функции ...

Почему конструктор вызывается при присвоении объекта другому объекту - C++
оператор+ выполняется нормально, но когда уже переменная в sum, на след шаге она вызывает конструктор, ибо у меня в примере 9 выходит. А в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru