C ++ выделяет память без активации конструкторов - PullRequest
5 голосов
/ 02 января 2011

Я читаю значения из файла, который я буду хранить в памяти при их чтении. Я читал здесь, что правильный способ обработки местоположения памяти в C ++ - всегда использовать new / delete, но еслиЯ делаю:

DataType* foo = new DataType[sizeof(DataType) * numDataTypes];

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

DataType* foo;
char* tempBuffer=new char[sizeof(DataType) * numDataTypes];
foo=(DataType*) tempBuffer;

Но я подумал, что это будет что-то напыщенное из-за некоторой небезопасности типа.Так что мне делать?

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

Ответы [ 7 ]

7 голосов
/ 02 января 2011

Используйте векторы !!!Поскольку вы знаете количество элементов, убедитесь, что вы зарезервировали память в первую очередь (вызвав myVector.reserve (numObjects), а затем вставьте элементы.).

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

Так что используйте

std::vector<DataType> myVector; // does not reserve anything
...
myVector.reserve(numObjects); // tells vector to reserve memory
5 голосов
/ 02 января 2011

Вы можете использовать ::operator new для выделения фрагмента памяти произвольного размера.

DataType* foo = static_cast<DataType*>(::operator new(sizeof(DataType) * numDataTypes));

Основное преимущество использования ::operator new над malloc в том, что оно генерирует ошибку и интегрируется с любыми new_handlers и т. Д. Вам необходимо очистить память с помощью ::operator delete

::operator delete(foo);

Обычный new Something, конечно, вызовет конструктор, в конце концов, в этом смысл new.

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

DataType dt;
read(fd, &dt, sizeof(dt));

Если вы делаете это, вы все равно уже выбрасываете тип безопасности в окно.

Почему вы пытаетесь достичь, не вызывая конструктор?

2 голосов
/ 02 января 2011

Вы можете выделить память с помощью new char[], вызвать требуемый конструктор для каждого элемента в массиве, и тогда все будет безопасно для типов.Прочитайте Каковы варианты использования конструкции C ++ "размещение нового"?

Так работает std::vector, поскольку он выделяет немного дополнительной памяти для эффективности, но не создает никаких объектовв дополнительной памяти, пока они на самом деле не нужны.

1 голос
/ 02 января 2011

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

./allocate < ints.txt

Тогда вы можете сделать:

#include <vector>
#include <iostream>

using namespace std;

class MyDataType {
public:
  int dataField;
};


int main() {

  const int TO_RESERVE = 10;

  vector<MyDataType> everything;
  everything.reserve( TO_RESERVE );

  MyDataType temp;
  while( cin >> temp.dataField ) {
    everything.push_back( temp );
  }

  for( unsigned i = 0; i < everything.size(); i++ ) {
    cout << everything[i].dataField;
    if( i < everything.size() - 1 ) {
      cout << ", ";
    }
  }
}

Что для меня со списком из 4 целых чисел дает:

5, 6, 2, 6
1 голос
/ 02 января 2011

Я думаю, вам не нужно заботиться об эффективности использования вектора, если вы не будете вставлять новые элементы нигде, кроме конца вектора (поскольку элементы вектора хранятся в непрерывном блоке памяти).

1 голос
/ 02 января 2011
vector<DataType> dataTypeVec(numDataTypes);

И, как вам сказали, ваша первая строка содержит ошибку (не нужно умножать на sizeof).

1 голос
/ 02 января 2011

Вы должны использовать вектор.Это позволит вам создавать его содержимое по одному (через push_back или подобное), что звучит как то, что вы хотите сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...