Динамическое создание std::vector // создание указателя на вектор

Я новичок, поэтому я, скорее всего, упустил что-то ключевое.

Я использую std::vector для хранения данных из операции ReadFile.

В настоящее время у меня есть структура READBUFF, которая содержит вектор байтов. Затем READBUFF создается через закрытый тип в классе Reader.

class Reader{
public:
void Read();
typedef struct {
std::vector<byte> buffer;
} READBUFF;

private:
READBUFF readBuffer;
}

В Read() я в настоящее время изменяю размер массива до желаемого размера, поскольку распределитель по умолчанию создает действительно большой вектор [4292060576]

void Reader::Read()
{
readBuffer.buffer.resize(8192);
}

Все это работает нормально, но потом я подумал, что лучше динамически НОВЫЙ встроенный вектор, чтобы я контролировал управление распределением указателя. Я изменил буфер на: std::vector* buffer. Когда я пытаюсь сделать следующий буфер, не устанавливается новый буфер. Из отладчика видно, что он не инициализирован.

void Reader::Read()
{
 key.buffer =  new std::vector<byte>(bufferSize);
}

Итак, я попытался, но это ведет себя так же, как указано выше.

void Reader::Read()
{
std::vector<byte> *pvector = new std::vector<byte>(8192);
key.buffer = pvector;
}

Главный первый вопрос: почему это не работает? Почему я не могу назначить указатель буфера допустимому указателю? Кроме того, как мне определить размер встроенного распределения по сравнению с необходимостью изменения размера?

Моя конечная цель - "обновить" буферы, а затем сохранить их в очереди. Прямо сейчас я делаю это, чтобы повторно использовать вышеуказанный буфер, но по сути я копирую буфер в другой новый буфер, когда все, что я хочу, это сохранить указатель на исходный буфер, который был создан.

 std::vector<byte> newBuffer(pKey->buffer);
 pKey->ptrFileReader->getBuffer()->Enqueue(newBuffer);

Заранее спасибо. Когда я публикую это, я понимаю, что упускаю что-то фундаментальное, но я в растерянности.


person Eric Schmidt    schedule 27.08.2011    source источник
comment
Какая? Распределитель по умолчанию создает вектор из 4-х гигаэлементов? Пожалуйста, скажите мне, какой компилятор вы используете, чтобы я мог держаться подальше от него.   -  person R. Martinho Fernandes    schedule 27.08.2011
comment
Динамическое распределение векторов — очень плохая идея. Просто не делай этого.   -  person fredoverflow    schedule 27.08.2011
comment
«распределитель по умолчанию создает действительно большой вектор». Распределитель по умолчанию не делает этого, возможно, вы имеете в виду конструктор по умолчанию, но он создает вектор нулевого размера. key.buffer = new std::vector<byte>(bufferSize); создаст вектор размера bufferSize и назначит указатель на него key.buffer. Вы говорите, что это не так, но это так. «Основной первый вопрос», вы делаете это точно так же, как пытаетесь это сделать, любой из опубликованных вами методов будет работать. Очевидно, что-то не так с тем, как вы интерпретируете то, что видите, но я понятия не имею, что именно. Ваш код в порядке, честно.   -  person john    schedule 27.08.2011
comment
Закрыто как "иди и почитай книгу".   -  person sbi    schedule 27.08.2011
comment
@Р. Мартиньо Фернандеш. Я использую MSVC2010. Я неправильно истолковал окно просмотра как выделенный размер? key.buffer.size() 4288718240, до выполнения какого-либо распределения. Я смотрел на средство просмотра процессов и не видел, чтобы мой рабочий набор изменился, отсюда и путаница.   -  person Eric Schmidt    schedule 28.08.2011
comment
@Джон. Спасибо, я буду продолжать использовать встроенное распределение для новых сообщений в соответствии с вашими примечаниями и заметками Сета ниже. Это было полезно.   -  person Eric Schmidt    schedule 28.08.2011
comment
@SBI.Я прочитал несколько книг, включая Стандартную библиотеку шаблонов C++ Джосуттиса. Я бы не публиковал, если бы не чувствовал себя застрявшим. Если есть дельный совет, буду рад.   -  person Eric Schmidt    schedule 28.08.2011
comment
@Eric: книга Джосуттиса называется «Стандартная библиотека C+». Это отличная книга, чтобы узнать, как использовать стандартную библиотеку C++, но я не книга, которая учит вас языку. См. The Definitive C++ Book Guide and List хорошие книги для изучения C++ .   -  person sbi    schedule 05.09.2011


Ответы (2)


Вы не должны использовать new в этом случае. Это заставляет вас управлять памятью вручную, что никогда вам не нужно делать по многим причинам1. Вы сказали, что хотите управлять временем жизни вектора, используя new; на самом деле время жизни вектора уже задано, потому что оно такое же, как и у объекта, который его содержит. Таким образом, время жизни этого вектора — это время жизни экземпляра вашего класса Reader.

Чтобы установить размер вектора до того, как он будет создан, вам нужно создать конструктор для READBUFF:

// inside the READBUFF struct (assuming you're using a normal variable, not a pointer)
READBUFF() { } // default constructor
READBUFF(int size) : buffer(size) { } // immediately sets buffer's size to the argument 

и используйте список инициализации в конструкторе Reader:

// inside the Reader class
Reader() : readBuffer(8092) { }

Что установит размер readBuffer.buffer равным 8092.


Если вы действительно хотите использовать new только для обучения:

key.buffer =  new std::vector<byte>(bufferSize);

Это будет работать нормально, но вы не должны делать это в функции Read, вы должны делать это в конструкторе объекта. Таким образом, любая функция-член может использовать его, не проверяя, является ли он NULL.

поскольку распределитель по умолчанию создает действительно большой вектор [4292060576]

Нет, это не так (если бы это было так, у вас мог бы быть один вектор на весь компьютер, и, вероятно, ваш компьютер вышел бы из строя). Он постепенно изменяет размер хранилища, когда вы добавляете вещи и превышаете емкость. Использование resize, как вы делаете, все же хорошо, потому что вместо того, чтобы выделять маленькое, заполнять его, выделять большее и копировать все, заполнять его, выделять большее и копировать все и т. д., вы просто выделяете размер, который вам нужен один раз, что намного быстрее.

1 Некоторые причины:

  1. Вы должны убедиться, что выделили его, прежде чем кто-либо еще его использует, где с обычной переменной-членом это делается автоматически, прежде чем ваш объект сможет его использовать.
  2. Вы должны помнить delete в деструкторе.
  3. Если вы не сделаете две вышеуказанные вещи, у вас либо ошибка сегментации, либо утечка памяти.
person Seth Carnegie    schedule 27.08.2011
comment
@celavek упс, спасибо, просто удивительно, какую разницу могут иметь 3 буквы. - person Seth Carnegie; 28.08.2011
comment
Нет ничего плохого в управлении собственной памятью. Как программист, вы должны знать при каждом запуске программы, какая память у вас есть, а какая нет. Отсутствие уже выделенной памяти является ошибкой новичка. Если вы забыли delete, это означает, что вы потеряли след своей собственной программы. Плохая примета. (Если вы боитесь памяти, вы всегда можете переключиться на java) - person Shahbaz; 28.08.2011
comment
@Shahbaz Тот факт, что я еще не выделил часть памяти, является очень ошибкой новичка, да, и характер этого вопроса побудил меня сказать это. И нет, нет ничего плохого в управлении собственной памятью, но зачем усложнять процесс ручного управления памятью, когда вы можете управлять ею автоматически? В этом случае вы ничего не получите от динамической памяти. - person Seth Carnegie; 28.08.2011
comment
@Сет Карнеги. В случае с этим вопросом, конечно. Я имею в виду, вы используете векторы, вы могли бы также использовать векторы векторов, верно? ;) - person Shahbaz; 28.08.2011
comment
@Сет Карнеги. Спасибо чувак. Вы попали в суть моего вопроса, который действительно касался управления памятью. Я получил крысиную нору из-за непонимания того, что прямое окно говорило мне в VS. Я полностью за неновый маршрут для векторов. Я пришел из мира .NET, а также из старого C (10 лет) назад, и, поскольку Шахбаз имеет право бояться памяти, моя цель состояла в том, чтобы лучше понять плюсы и минусы здесь. Я получаю это сейчас. - person Eric Schmidt; 28.08.2011
comment
@Eric рад помочь, удачи в вашем проекте и на пути к нирване C++. - person Seth Carnegie; 28.08.2011

Я думаю, вы можете неправильно интерпретировать результат вызова max_size() для вектора:

#include <vector>
#include <iostream>

int main() {
  std::cout << std::vector<char>().max_size() << std::endl;
  std::cout << std::vector<char>::size_type(~0) << std::endl;
}

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

person Flexo    schedule 27.08.2011
comment
спасибо, как я уже отмечал выше, я неправильно прочитал окно отладки/немедленного действия - до фактического распределения или изменения размера. - person Eric Schmidt; 28.08.2011