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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 29, средняя оценка - 5.00
Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
#1

Освобождение памяти, занятой вектором - C++

07.09.2011, 14:30. Просмотров 3783. Ответов 62
Метки нет (Все метки)

У меня задача требует чтобы у вектора было в резерве не более 100 элементов. При постоянном росте вектора понятно как это обеспечить, а вот как быть при уменьшении количества элементов? Я не в курсе последних стандартов, подскажите есть ли сейчас способы гарантированного освобождения памяти, занятой вектором, и вообще какие способы существуют?
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.09.2011, 14:30
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Освобождение памяти, занятой вектором (C++):

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

резервирование памяти/освобождение памяти для трехмерного массива - C++
Необходимо создать трехмерный массив (A), в котором элементы вдоль направления Z выли бы выровнены по 16 байт. Есть две проблемы: ...

Освобождение памяти в C++ - C++
Добрый день! В моей программе в функции выделяется память (new char) под символьный массив, который является элементом структуры. Это...

Освобождение памяти - C++
Похоже что проблема с освобождением памяти. У меня есть абстрактный класс CObject и его потомок CMeteor, в котором реализованы...

Освобождение памяти - C++
Собственно есть простенький класс class Human { public: Human ( ); void ptintHuman(); private: static long...

Освобождение памяти - C++
#include<iostream> #include<cstring> using namespace std; struct stringy{ char * str; int ct; }; stringy & set(stringy &...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
-=ЮрА=-
Заблокирован
Автор FAQ
07.09.2011, 20:33 #31
Цитата Сообщение от grizlik78 Посмотреть сообщение
жасно. Вернее не так: Ужас-ужас.
- Так полегчает???

Цитата Сообщение от talis Посмотреть сообщение
-=ЮрА=-, вы вообще знаете, зачем нужны конструкторы и деструкторы? Вы понимаете, что конструктор вашего класса не вызывается? Проверьте:
- неа я из каменного века, но как вариант предлагаю это скомпилировать
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
#include <windows.h>
#include <stdio.h>
 
class SimpleClass
{
private :
    char sMSG[256];
public:
    SimpleClass(){strcpy(sMSG,"I'm created");}
    void CheckStatus(){printf("%s\r\n",sMSG);}
};
 
 
int main()
{
    SimpleClass * ptr = (SimpleClass *)malloc(sizeof(SimpleClass));
    printf("Enter num of exemlars : ");
    unsigned long n;scanf("%u",&n);
    ptr = (SimpleClass *)realloc((void *)ptr,n*sizeof(SimpleClass));
    for(unsigned long i = 0;i < n; i++)
    {
        ptr[i] = SimpleClass();
        ptr[i].CheckStatus();
    }
    system("pause");
    return 0;
}
Я всего лишь предлагаю ТС вправе выбрать то что ему по душе
0
Миниатюры
Освобождение памяти, занятой вектором  
-=ЮрА=-
Заблокирован
Автор FAQ
07.09.2011, 20:36 #32
PS:
SimpleClass(){strcpy(sMSG,"I'm created");}//Инициализировал переменную класса
void CheckStatus(){printf("%s\r\n",sMSG);} //Вывод переменной

C++
1
ptr[i] = SimpleClass();
- говорю делов ноль
0
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
07.09.2011, 20:44 #33
-=ЮрА=-, а если после этого нужно изменить количество SimpleClass'ов? realloc? а как же деструкторы в случае уменьшения количества экземпляров или конструкторы в случае увеличения?

Добавлено через 5 минут
Так вот не проще:

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>
#include <conio.h>
#include <cstring>
#include <vector>
 
class SimpleClass
{
private :
        char sMSG[256];
 
public:
        SimpleClass(){ strcpy(sMSG,"I'm created"); }
        void CheckStatus(){ printf("%s\r\n",sMSG); }
};
 
 
int main()
{
        printf("Enter num of exemlars : ");
 
        unsigned long n;
        scanf("%u",&n);
 
        std::vector<SimpleClass> vec ( n );
 
        for( unsigned long i = 0; i < n; i++ )
        {
            printf( "%i: ", i );
            vec[i].CheckStatus();
        }
 
        puts( "-------------" );
        getch();
 
        vec.resize( n*2 );
 
        for( unsigned long i = 0; i < n*2; i++ )
        {
            printf( "%i: ", i );
            vec[i].CheckStatus();
        }
 
        puts( "-------------" );
        getch();
 
        vec.resize( n/2 );
 
        for( unsigned long i = 0; i < n/2; i++ )
        {
            printf( "%i: ", i );
            vec[i].CheckStatus();
        }
 
 
 
        return 0;
}
0
-=ЮрА=-
Заблокирован
Автор FAQ
07.09.2011, 22:13 #34
Цитата Сообщение от talis Посмотреть сообщение
-=ЮрА=-, а если после этого нужно изменить количество SimpleClass'ов? realloc? а как же деструкторы в случае уменьшения количества экземпляров или конструкторы в случае увеличения?
Вот доработал свой наглядный пример

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <windows.h>
#include <stdio.h>
 
 
class SimpleClass
{
private :
    unsigned long num;
    char sMSG[256];
    bool bCreated;
public:
    SimpleClass(int i)
    {
        bCreated = true;
        sprintf(sMSG,"class %u - I'm created",1 + (num = i));
    }
    ~SimpleClass()
    {
        sprintf(sMSG,"class %u - I'm destroyed",1 + num);
    }
    void CheckStatus()
    {
        printf("%s\r\n",sMSG);
    }
};
 
 
int main()
{
    SimpleClass * ptr = (SimpleClass *)malloc(sizeof(SimpleClass));
    printf("Enter num of examles : ");
    unsigned long i,n;scanf("%u",&n);
    ptr = (SimpleClass *)realloc((void *)ptr,n*sizeof(SimpleClass));
    for(i = 0;i < n; i++)
    {
        ptr[i] = SimpleClass(i);
        ptr[i].CheckStatus();
    }
    printf("Enter new num examles: ");
    unsigned long m;scanf("%u",&m);
    
    if(m < n)
    {
        for(i = n - 1;m <= i; i--)
        {
            ptr[i].~SimpleClass();//Дструктор ничего не делает
            ptr[i].CheckStatus();//поэтому вывожу CheckStatus,
                        //в реалии ~ удаляят всё, поєтому потом уже ничего не вызвать
                        //всё сделал чисто в ознакомительных целях
        }
        ptr = (SimpleClass *)realloc((void *)ptr,m*sizeof(SimpleClass));
    }
    else
    {
        ptr = (SimpleClass *)realloc((void *)ptr,m*sizeof(SimpleClass));
        for(i = n - 1;i < m; i++)
        {
            ptr[i] = SimpleClass(i);
            ptr[i].CheckStatus();
        }
    }
    system("pause");
    return 0;
}
0
Миниатюры
Освобождение памяти, занятой вектором  
Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
07.09.2011, 22:33  [ТС] #35
Насколько мне было известно, ранее swap трюк не гарантировал освобождение памяти. В стандарте не было прописано что при этом должно выделиться меньше памяти под новый вектор. Теперь это не так?

Насчет того, что многие уверены что память вообще не нужно освобождать, в моём проекте, в тз отдельным пунктом идёт ограничение памяти под сервак 512 мегабайт. При этом нагрузка не прописана, будет работать на мощном сервере, с быстрой памятью и процом и поэтому частота переаллокаций не имеет никакого значения.
А сервак - что-то типо логера, он собрал одни данные, скинул их в базу, и далее данные надо частично затереть, т.к. параллельно в разное время начинают собираться отдельные массивы, каждый около 100 мегабайт. Если не чистить, то все 10 массивов разрастутся до 1 гб, а если чистить, то вполне можно уложиться в отведенный объем озу.
Т.ч. такие задачи существуют.
0
villu
203 / 204 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
07.09.2011, 22:35 #36
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
- неа я из каменного века, но как вариант предлагаю это скомпилировать
можно узнать что за среда? подозреваю, что realloc и malloc просто перебиты чем-то. Linux, gcc совершенно другое поведение. То есть память выделяется но конструкторы, как и положено, не вызываются.

а не, понял. не скопировал присваивание.
0
Union
17 / 17 / 2
Регистрация: 16.08.2010
Сообщений: 252
07.09.2011, 22:39  [ТС] #37
Linux, но вектор, всмысле stl - кроссплатформенный, поэтому задал вопрос в данном разделе
0
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
08.09.2011, 00:58 #38
Union, вот мои эксперименты:

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <iostream>
#include <vector>
#include <string>
#include <memory>
 
using namespace std;
 
int alloc_counter = 0;
int dealloc_counter = 0;
 
class CDummy
{
private:
    //char huge_data[ 8192 ];
 
public:
    CDummy(){};
    CDummy( const CDummy &d ){ };
 
    ~CDummy(){ cout << "~ "; };
};
 
namespace std
{
    template<>
    class allocator<CDummy>
    {
    public:
      typedef size_t     size_type;
      typedef ptrdiff_t  difference_type;
      typedef CDummy*       pointer;
      typedef const CDummy* const_pointer;
      typedef CDummy&       reference;
      typedef const CDummy& const_reference;
      typedef CDummy        value_type;
 
      template<typename _Tp1>
      struct rebind
      {
          typedef allocator<_Tp1> other;
      };
 
      pointer allocate( size_type sz, const void* = 0 )
      {
          cout << "\nALLOCATE " << sz << " ITEMS\n";
          alloc_counter++;
          return (CDummy*) operator new( sz * sizeof( CDummy ) );
      }
 
      void construct(pointer ptr, const reference val)
      {
          cout << "CONSTRUCT\n";
          new ( (void *) ptr ) CDummy( val );
      }
 
      void deallocate( pointer ptr, size_type sz )
      {
          cout << "\nDEALLOCATE " << sz << " ITEMS\n";
          dealloc_counter++;
          delete ptr;
      }
 
      void destroy( pointer ptr )
      {
          cout << "DESTROY\n";
          ptr->~CDummy();
      }
 
      size_type max_size() const
      {
          return size_t(-1) / sizeof( CDummy );
      }
 
    };
};
 
int main()
{
    {
        vector<CDummy> vec (0);
 
        string input;
        int n;
 
        for(;;)
        {
            cout << '>';
            cin >> input;
 
            if( input == "add")
            {
                cin >> n;
                vec.resize( vec.size() + n );
            }
            else if( input == "del" )
            {
                cin >> n;
                vec.resize( vec.size() - n );
            }
            else if( input == "size" )
                cout << vec.size() << '\n';
            else if( input == "memstat" )
                cout << "allocations: " << alloc_counter
                     << "; deallocations: " << dealloc_counter << '\n';
            else if( input == "quit" )
                break;
            else
                cout << "what?\n";
 
            cout << '\n';
        }
 
        vec.clear();
    } // vec тут уничтожается
 
    cout << "\n\nallocations: " << alloc_counter << "; deallocations: " << dealloc_counter << "\n\n\n";
 
    return 0;
}
На выводе каждый вызов деструктора обозначается символом тильды. Попробуйте ввести эту последовательность команд:

add 5
add 70
add 100
memstat
size
del 170
memstat
size
add 40
add 20
memstat

У меня (gcc 4.6) вектор выделяет память при расширении. При уменьшении количества элементов он вызывает деструкторы (кстати, обходя void destroy( pointer )), но память не отдаёт. После уничтожения самого объекта вектора (введите quit) он отдаст память, но там уже поздновато будет.
0
-=ЮрА=-
Заблокирован
Автор FAQ
08.09.2011, 10:16 #39
Цитата Сообщение от villu Посмотреть сообщение
подозреваю, что realloc и malloc просто перебиты чем-то
- ОС XP 32 VisualStudio 6.0

Добавлено через 1 минуту
Цитата Сообщение от talis Посмотреть сообщение
меня (gcc 4.6) вектор выделяет память при расширении. При уменьшении количества элементов он вызывает деструкторы (кстати, обходя void destroy( pointer )), но память не отдаёт. После уничтожения самого объекта вектора (введите quit) он отдаст память, но там уже поздновато будет.
Сначало вызвать деструкторы для нужных объектов, потом обрезать память, в моём примере именно так и сделано...
0
alex_x_x
бжни
2447 / 1652 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
08.09.2011, 10:54 #40
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Сначало вызвать деструкторы для нужных объектов, потом обрезать память, в моём примере именно так и сделано...
вы вызываете конструктор анонимного объекта, а потом присваивание и это печально
правильно в вашем примере будет так и только так как у talis, с использованием placement new
0
-=ЮрА=-
Заблокирован
Автор FAQ
08.09.2011, 11:34 #41
Цитата Сообщение от alex_x_x Посмотреть сообщение
конструктор анонимного объекта
- поэтому и ввёл int i в конструктор, т.е в реальной программе - это наша начальная инициализация, что сделать массив CFileDialog с тайтлами появляющихся окон Окно № i ???Я уже устал от разборов, сейчас накидаю проект...
0
fasked
Эксперт С++
4936 / 2516 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
08.09.2011, 11:36 #42
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
поэтому и ввёл int i в конструктор, т.е в реальной программе - это наша начальная инициализация, что сделать массив CFileDialog с тайтлами появляющихся окон Окно № i ???Я уже устал от разборов, сейчас накидаю проект...
Да не нужны никому эти CFileDialog, мы даже посмотреть не сможем на результат, окромя Ваших скринов... Просто создайте простенький класс, в котором динамически выделяется память в конструкторе и освобождается в деструкторе.
0
Deviaphan
Делаю внезапно и красиво
Эксперт C++
1287 / 1221 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
08.09.2011, 11:44 #43
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
неа я из каменного века
Именно из него. Перед присваиванием нужно разрушить текущее состояние объекта, но никакого состояния нет, т.к там мусор. В данном случае код работает исключительно по ошибке, для не POD типов этот код не работает. Т.е. можно утверждать, что он НЕ рабочий. Причём, даже вызов memset после перераспределения памяти не сделает этот код рабочим. В общем, не надо так никогда делать.
0
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
08.09.2011, 11:49 #44
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Сначало вызвать деструкторы для нужных объектов, потом обрезать память, в моём примере именно так и сделано...
Юра, а вы залезьте в недры заголовочников вашего компилятора и посмотрите, как устроен std::allocator (и классы, от которых он наследует). Там так и сделано. Одна функция (метод, если вам угодно) - это deallocate, другая - destroy.

Вся STL работает по принципу "конструктор-деструктор", так, как Страуструп прописал. Все человеческие библиотеки так работают. Вы ведь не с нами спорите, вы ведь со стандартом C++ и с нормами ООП спорите. Не занимайтесь ерундой, почитайте, лучше, умных книжек. Ну или, хотя бы, вот это. Про назначение конструктора в особенности.
0
Deviaphan
Делаю внезапно и красиво
Эксперт C++
1287 / 1221 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
08.09.2011, 11:52 #45
Цитата Сообщение от Union Посмотреть сообщение
задача требует чтобы у вектора было в резерве не более 100 элементов.
Стоит задуматься об использовании иных контейнеров, т.к. при большом количестве элементов распределение памяти становится неэффективным. Стандартная реализация обеспечивает в среднем два копирования при любом размере vector'a. Если в резерве держать не более 100 элементов, то копирований будет намного больше(чем больше длина вектора, тем больше лишних копирований).
Особенно это критично будет при неэффективном копировании вектора больших объектов.
1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.09.2011, 11:52
Привет! Вот еще темы с ответами:

Освобождение памяти - C++
Есть класс, в котором я выделяю память с помощью new. В деструкторе класса я с помощью delete освобождаю память, но у меня вылетает ошибка...

Освобождение памяти - C++
Маленький вопросик, как правильно освобождать память выделенную под vector&lt;...&gt;, деструктором ~vector() или методом clear() ?

Освобождение памяти - C++
Как сделать, чтобы при вызове деструктора экземпляра i класса image, вызвался и деструктор класса image_bmp? class image { public:...

Освобождение памяти в c++ - C++
Привет, помогите разобраться с освобождением памяти в c++. Я так понимаю, что если освободить память, то переменная удаляется, но почему же...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
08.09.2011, 11:52
Ответ Создать тему
Опции темы

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