Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
161 / 161 / 68
Регистрация: 23.02.2011
Сообщений: 392
1

Память под объекты через new

23.07.2012, 02:57. Просмотров 1363. Ответов 18
Метки нет (Все метки)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
 
class A
{
public:
    int my;
};
 
 
int main()
{
    A* a = new A();
    A* b = new A();
    A* c;
    A* d;
 
    A f;
 
    std::cout << a << std::endl
              << b << std::endl
              << c << std::endl
              << d << std::endl;
 
    std::cout << std::endl;
 
    delete a;
    delete b;
}
Куски памяти под a и b распределяются друг за другом, а под c и d совсем в разных местах. Из-за чего так? Из-за того, что a и b указывают на существующий в памяти объект, а c и d - нет? И желательно ли писать:
C++
1
2
    A* c = NULL;
    A* d = NULL;
Да и вообще, принципиальной разницы между
C++
1
2
    a->my = 4;
    f.my = 5;
нету, да?(Я понимаю, что в первом случае обращение идёт через указатель, а во втором напрямую.) И какой из этих вариантов наиболее часто используется в практике? Или здесь так же, как и в случае
C++
1
2
    int* s = new int(6);
    std::cout << *s;
в практике почти не встречается и указатель требуется только для создания массивов объектов?

ЗЫ: Есть ли отличие:
C++
1
2
3
A* a = new A;
//и
A* a = new A();
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.07.2012, 02:57
Ответы с готовыми решениями:

Динамичная память под объекты
Правильно ли я заполняю поля объектов с помощю методов в динамическом массиве из объектов.Все...

Можно ли динамически выделить память под массив указателей, на объекты класса?
Прошу прощения если не правильно назвал вопрос. Не знаю как правильно сформулировать. Можно ли...

Как освободить память, выделенную через new под матрицу?
Здравствуйте!!! Почему-то никак не освобождается память, выделенная оператором new под двумерный...

Динамическая память. Функции. Массивы .Объекты
Всем привет. Возник следующий вопрос: 1.Когда в c++ из функции возвращается объект (экземпляр...

18
5473 / 4868 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
23.07.2012, 04:53 2
Цитата Сообщение от edward_jonson Посмотреть сообщение
A* c = NULL;
A* d = NULL;
Без этого, MSVC ошибку при выполнении выдаёт: обращение к неинициализированнной переменной в строках 21 и 22, если продолжить, то адреса: СССССССС, СССССССС. mingv пропускает и выдаёт: 0x100, 0x4016dd. Вывод: желательно писать, или, хотя бы не обращаться к переменным до инициализации.

Цитата Сообщение от edward_jonson Посмотреть сообщение
A* a = new A;
//и
A* a = new A()
Без разницы. Конструктор по умолчанию.

Цитата Сообщение от edward_jonson Посмотреть сообщение
Да и вообще, принципиальной разницы между
a->my = 4;
f.my = 5;
нету, да?(Я понимаю, что в первом случае обращение идёт через указатель, а во втором напрямую.) И какой из этих вариантов наиболее часто используется в практике?
Разница в том, что в первом случае указатель, а во втором объект. В практике используется тот, который нужен. К объекту -> не приделаешь. Другое дело, что первый пример можно записать двумя способами: a -> my = 4; или (*a).my = 4; Тут, действительно, принципиальной разницы нет. Пусть эксперты скажут, для хорошего стиля программирования, какой лучше ?

Цитата Сообщение от edward_jonson Посмотреть сообщение
Куски памяти под a и b распределяются друг за другом, а под c и d совсем в разных местах.
Тут нужно разделить понятия: память под переменные a, b, c, d (под указатели) и память под то, на что эти указатели указывают. У вас у коде, а и b содержат адреса в динамической области памяти, по которым находятся созданные объекты класса А, а с и d не на что не указывают, в них, по идее, "мусор" должен быть (поэтому разные компиляторы по разному и обрабатывают вывод их содержимого через cout <<). Чтобы узнать адреса самих переменных нужно написать:
C++
1
2
3
4
std::cout << &a << std::endl
              << &b << std::endl
              << &c << std::endl
              << &d << std::endl;
Под них память выделена подряд, и (если я неправ, пусть поправят) в стеке. Если же так написать:
C++
1
2
3
4
5
6
7
8
A* a = new A();
A* b = new A;
A c;
A d;
std::cout << a << std::endl
          << b << std::endl
          << &c << std::endl
          << &d << std::endl;
, то выведутся адреса динамической памяти, содержащиеся в a и b , и адреса объектов c и d, созданных в автоматической области памяти (в стеке).
2
Каратель
Эксперт С++
6593 / 4014 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
23.07.2012, 10:46 3
Лучший ответ Сообщение было отмечено как решение

Решение

Цитата Сообщение от edward_jonson Посмотреть сообщение
ЗЫ: Есть ли отличие
есть:
для POD типов конструктор не вызывается т.е.
C++
1
2
int* a = new int; //значение a - мусор
int* b = new int(); //значение b == 0
3
161 / 161 / 68
Регистрация: 23.02.2011
Сообщений: 392
23.07.2012, 15:06  [ТС] 4
Jupiter, ну а если в класс A добавить конструктор -
C++
1
2
3
4
5
6
class A
{
public:
    int my;
    A() : my(4){}
};
то уже разницы между
C++
1
A* s = new A();
и
C++
1
A* s = new A;
не будет, т.к. в обоих случаях будет вызываться пользовательский конструктор по умолчанию?
0
2818 / 1628 / 252
Регистрация: 03.12.2007
Сообщений: 4,223
23.07.2012, 15:14 5
Цитата Сообщение от alsav22 Посмотреть сообщение
К объекту -> не приделаешь.
Почему? Можно перегрузить operator->
1
161 / 161 / 68
Регистрация: 23.02.2011
Сообщений: 392
23.07.2012, 16:25  [ТС] 6
Цитата Сообщение от alsav22 Посмотреть сообщение
Разница в том, что в первом случае указатель, а во втором объект. В практике используется тот, который нужен. К объекту -> не приделаешь. Другое дело, что первый пример можно записать двумя способами: a -> my = 4; или (*a).my = 4; Тут, действительно, принципиальной разницы нет. Пусть эксперты скажут, для хорошего стиля программирования, какой лучше ?
Да можно даже написать
C++
1
2
A a;
(&a)->my = 4;
Только не думаю, что кто-то будет)
0
5473 / 4868 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
23.07.2012, 21:41 7
Цитата Сообщение от Jupiter Посмотреть сообщение
есть:
для POD типов конструктор не вызывается т.е.
C++
1
2
int* a = new int; //значение a - мусор
int* b = new int(); //значение b == 0
Что-то я здесь ни мусора, ни 0 не вижу...
0
Миниатюры
Память под объекты через new   Память под объекты через new  
Каратель
Эксперт С++
6593 / 4014 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
23.07.2012, 21:43 8
Цитата Сообщение от alsav22 Посмотреть сообщение
Что-то я здесь мусора не вижу...
C++
1
std::cout << *a << std::endl << *b << std::endl;
1
5473 / 4868 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
23.07.2012, 22:09 9
Если так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
 
class A
{
public:
    int my;
    A(){std::cout << "K" << std::endl;}
};
 
int main()
{
    A* a = new A;
    A* b = new A();
    std::cout << a -> my << std::endl << b -> my << std::endl;
    std::cout << std::endl;
 
    delete a;
    delete b;
 
    system("pause");
    return 0;
}
, то конструктор вызывается, в my, и в a и в b мусор. Почему в b не 0, если должно *b == 0 ? Или это для int будет?
0
Каратель
Эксперт С++
6593 / 4014 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
23.07.2012, 22:21 10
Цитата Сообщение от alsav22 Посмотреть сообщение
Почему в b не 0, если должно *b == 0 ? Или это для int будет?
инициализация POD-типов полностью возложена на программиста

Не по теме:

что такое POD-типы - в поиск, а лучше в последний стандарт, ЕМНИП там были внесены изменения в понятие POD-типов

1
Эксперт С++
8302 / 6056 / 602
Регистрация: 10.12.2010
Сообщений: 28,148
Записей в блоге: 26
24.07.2012, 23:37 11
Конструктор не правильный
C++
1
A():my(0){std::cout << "K" << std::endl;}
0
5473 / 4868 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
25.07.2012, 00:30 12
Цитата Сообщение от Avazart Посмотреть сообщение
Конструктор не правильный
C++
1
A():my(0){std::cout << "K" << std::endl;}
Так и задумано было. Я тут другое выяснял. Jupiter, написал, что если так:
int* a = new int; //значение a - мусор
int* b = new int(); //значение b == 0
, т.е. память, на которую указывает b, будет заполнена 0 и конструктор не будет вызываться. Вот я и проверил для класса. std::cout << "K" << std::endl; это только, чтобы проверить срабатывает конструктор или нет, а my специально неинициализировал. Но дело тут ещё в том (Jupiter дальше написал), что есть POD, а что не POD.
0
69 / 63 / 5
Регистрация: 09.06.2012
Сообщений: 291
25.07.2012, 07:56 13
хм,а я и не знал,спасибо юпитер

C++
1
2
3
4
5
6
7
8
9
        
        int *pr = new int;
    int *pr1 = new int();
 
    std::cout << "pr = " << *pr << std::endl;
    std::cout << "pr1 = " << *pr1 << std::endl;
 
    delete pr;
    delete pr1;
0
Эксперт С++
8302 / 6056 / 602
Регистрация: 10.12.2010
Сообщений: 28,148
Записей в блоге: 26
25.07.2012, 10:31 14
g++ вывод:
Код
pr = 0
pr1 = 0
А в чем разница?
Разве есть рахнзница между int и int() ?
0
5473 / 4868 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
25.07.2012, 11:23 15
MSVC и mingv.
0
Миниатюры
Память под объекты через new   Память под объекты через new  
Каратель
Эксперт С++
6593 / 4014 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
25.07.2012, 11:38 16
Цитата Сообщение от Avazart Посмотреть сообщение
А в чем разница?
Разве есть рахнзница между int и int() ?
8-я глава черновика последнего стандарта, подраздел инициализаторы
8.5
An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
чуть выше пояснение
To value-initialize an object of type T means:
— if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the
default constructor for T is called (and the initialization is ill-formed if T has no accessible default
constructor);
— if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object
is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is
called.
— if T is an array type, then each element is value-initialized;
— otherwise, the object is zero-initialized.
и ещё чуть выше
To zero-initialize an object or reference of type T means:
— if T is a scalar type (3.9), the object is set to the value 0 (zero), taken as an integral constant expression,
converted to T;103
— if T is a (possibly cv-qualified) non-union class type, each non-static data member and each base-class
subobject is zero-initialized;
— if T is a (possibly cv-qualified) union type, the object’s first non-static named data member is zero-
initialized;
— if T is an array type, each element is zero-initialized;
— if T is a reference type, no initialization is performed.
0
161 / 161 / 68
Регистрация: 23.02.2011
Сообщений: 392
25.07.2012, 16:32  [ТС] 17
ВЫВОД:
Если в классе A имеется любой пользовательский конструктор по умолчанию, то разницы между
C++
1
A* a = new A();
и
C++
1
A* a = new A;
нет (либо в обоих классах в полях будет мусор, либо то, чем поля инициализированы в конструкторе по умолчанию), если же в классе конструктора по умолчанию нет, то в случае
C++
1
A* a = new A();
поля будут инициализированы 0, а в случае
C++
1
A* a = new A;
там будет мусор. (Со стандартными типами данных так же, как и с классами без конструктора по умолчанию).
0
Эксперт С++
8302 / 6056 / 602
Регистрация: 10.12.2010
Сообщений: 28,148
Записей в блоге: 26
25.07.2012, 16:41 18
Думаю несовсем так.
Зависит от того каким будет класс POD - ом или нет, а на это влияет не только наличие конструктора.
0
5473 / 4868 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
25.07.2012, 23:40 19
Цитата Сообщение от edward_jonson Посмотреть сообщение
если же в классе конструктора по умолчанию нет
К POD-типам относятся:
все встроенные арифметические типы (включая wchar_t и bool);
энумераторы, т.е. типы, объявленные с помощью ключевого слова enum;
все указатели;
POD-структуры (struct или class) и POD-объединения (union), которые удовлетворяют всем нижеприведенным требованиям:
не содержат пользовательских конструкторов, деструктора или копирующего оператора присваивания (копирующий оператор присваивания – это такой нешаблонный нестатический operator=, у которого есть строго один параметр типа X, X&, const X&, volatile X& или const volatile X&, где X – тип рассматриваемой структуры или объединения);
не имеют базовых классов;
не содержат виртуальных функций;
не содержат защищенных (protected) или закрытых (private) нестатических членов данных;
не содержат нестатических членов данных не-POD-типов (или массивов из таких типов), а также ссылок.
Соответственно, все оставшиеся объектные типы являются не-POD-типами.
Примечание: наличие квалификаторов const и volatile не влияет на «POD-овость» типа.
Если так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
 
class A
{
public:
    int my;
    ~A(){}
};
 
int main()
{
    A* a = new A;
    A* b = new A();
    std::cout << a -> my << std::endl << b -> my << std::endl;
    std::cout << std::endl;
 
    delete a;
    delete b;
 
    system("pause");
    return 0;
}
, то класс А уже не POD, и в b -> my мусор.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.07.2012, 23:40

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Можно ли записывать объекты класса string в память, чтоб потом их прочитать?
Создал класс, который содержит много объектов класса string, но что то не так как надо. В debug...

Перераспределение памяти с new под объекты
есть класс #include &lt;iostream&gt; #include &lt;string&gt; using namespace std; class tel_book {...

Динамическая память под объекты
Всем привет! Начал изучать язык ассемблера (intel) и появилось куча вопросов. Собественно...

Где выделяется память под объекты
Здравствуйте.Подскажите ,пожалуйста ,с небольшим недопониманием насчёт выделения памяти под...


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

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

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