Векторы стл с хранения неинициализированным?

Я'м пишу внутренний цикл, который должен поставить структуры в непрерывной памяти. Я не'т знаю, сколько эти структуры будут загодя. Моя проблема заключается в том, что стл'ывекторинициализирует его значениями в 0, так что неважно, что я делаю, я беру стоимость инициализации плюс стоимость установкиструктура`'s членов их значения.

Есть ли способ, чтобы предотвратить инициализацию, или есть в STL-контейнер, как там с перемещаемом непрерывного хранения и неинициализированные элементы?

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

Кроме того, см. Мой комментарий ниже для получения разъяснений о том, когда инициализация происходит.

НЕКОТОРЫЕ КОД:

void GetsCalledALot(int* data1, int* data2, int count) {
    int mvSize = memberVector.size()
    memberVector.resize(mvSize + count); // causes 0-initialization

    for (int i = 0; i < count; ++i) {
        memberVector[mvSize + i].d1 = data1[i];
        memberVector[mvSize + i].d2 = data2[i];
    }
}
Комментарии к вопросу (6)
Решение

СТД::вектор должен инициализировать значения в массиве, то, значит, у кого-конструктор (или копию-конструктор) должен быть вызван. Поведение "вектор" (или любой контейнер, класс) неопределено, если вы были, чтобы получить доступ к неинициализированной секции массива, как если бы он был инициализирован.

Лучшим способом является использование резерва () и push_back()`, так что копия-конструктор используется, во избежание дефолта-строительство.

Используя Ваш пример кода:

struct YourData {
    int d1;
    int d2;
    YourData(int v1, int v2) : d1(v1), d2(v2) {}
};

std::vector memberVector;

void GetsCalledALot(int* data1, int* data2, int count) {
    int mvSize = memberVector.size();

    // Does not initialize the extra elements
    memberVector.reserve(mvSize + count);

    // Note: consider using std::generate_n or std::copy instead of this loop.
    for (int i = 0; i < count; ++i) {
        // Copy construct using a temporary.
        memberVector.push_back(YourData(data1[i], data2[i]));
    }
}

Единственная проблема, с запасом звонит () (или изменить размер()) как это, что вы можете в конечном итоге вызывая командлет copy-конструктор чаще, чем нужно. Если вы можете сделать хороший прогноз, так как на конечный размер массива, он's лучше, чтобы резерв()` пространство, один раз в начале. Если вы Don'т знаем конечный размер, хотя, по крайней мере, число копий будет минимальный в среднем.

В текущей версии C++, внутренний цикл-это немного неэффективно, как временная ценность создается на стеке, копии-построено в памяти векторов, и, наконец, временно разрушается. Однако в следующей версии C++ есть функция, которая называется R-значение ссылки (Т&&), которая поможет.

Интерфейс поставляется `СТД::вектор не допускает и другой вариант, который используют некоторые фабрики класса для построения значений по умолчанию. Вот грубый пример того, что этот шаблон будет выглядеть реализована на языке C++:

template 
class my_vector_replacement {

    // ...

    template 
    my_vector::push_back_using_factory(F factory) {
        // ... check size of array, and resize if needed.

        // Copy construct using placement new,
        new(arrayData+end) T(factory())
        end += sizeof(T);
    }

    char* arrayData;
    size_t end; // Of initialized data in arrayData
};

// One of many possible implementations
struct MyFactory {
    MyFactory(int* p1, int* p2) : d1(p1), d2(p2) {}
    YourData operator()() const {
        return YourData(*d1,*d2);
    }
    int* d1;
    int* d2;
};

void GetsCalledALot(int* data1, int* data2, int count) {
    // ... Still will need the same call to a reserve() type function.

    // Note: consider using std::generate_n or std::copy instead of this loop.
    for (int i = 0; i < count; ++i) {
        // Copy construct using a factory
        memberVector.push_back_using_factory(MyFactory(data1+i, data2+i));
    }
}

Этим означает, что вы должны создать свой собственный класс Vector. В этом случае она также усложняет то, что должно было быть простой пример. Но могут быть случаи, когда с помощью функции фабрики, как это лучше, например, если вставить условно на некоторое другое значение, и вы должны были бы в противном случае безоговорочно построить какое-нибудь дорогостоящее временное, даже если бы это было'т действительно необходимо.

Комментарии (0)

В C++0х добавляет новый шаблон функции-члена emplace_back до Вектор (которая опирается на шаблоны с переменным числом аргументов и точная пересылка), что позволяет избавиться от любых временных целиком:

memberVector.emplace_back(data1[i], data2[i]);
Комментарии (0)

Чтобы уточнить на резерв() ответы: вам нужно использовать резерв() в сочетании с push_back(). Таким образом, конструктор по умолчанию не вызывается для каждого элемента, а конструктор копирования. Вы все равно понесете наказание за настройку структуры на стеке, а затем скопировать его в вектор. С другой стороны, это's возможно, что если вы используете

vect.push_back(MyStruct(fieldValue1, fieldValue2))

компилятор будет создавать новый экземпляр непосредственно в thatbelongs памяти для вектора. Это зависит от того, как умный оптимизатор. Вам нужно проверить сгенерированный код, чтобы узнать.

Комментарии (1)

В C++11 (и увеличения) можно использовать массив версия `unique_ptr не выделять неинициализированный массив. Это'т достаточно контейнеров STL, но все же управляемой памяти и C++-иш чего будет достаточно для многих приложений.

auto my_uninit_array = std::unique_ptr(new mystruct[count]);
Комментарии (0)

Так вот'проблема с resize-это призвание вставка, которая делает конструкцию копирование из умолчанию созданный элемент для каждого из вновь добавленных элементов. Чтобы получить это значение в 0 Стоимость вам нужно написать свой собственный конструктор по умолчанию и свой собственный конструктор копирования в качестве пустой функции. Делаю это в ваш конструктор копирования-это очень плохая идея так как это приведет к СТД::вектор'алгоритмы внутреннего перераспределения с.

Резюме: вы'вновь не собираюсь быть в состоянии сделать это с std::вектор.

Комментарии (1)

Эээ...

попробуйте способ:

std::vector::reserve(x)

Это позволит вам зарезервировать достаточно памяти для х предметов без инициализации (ваш вектор остается пустым). Таким образом, выиграл'т быть перераспределение до переметнуться х.

Второй момент заключается в том, что вектор выиграл'т инициализации значений до нуля. Вы тестируете свой код в режиме отладки ?

После проверки на G++ следующий код:


#include 
#include 

struct MyStruct
{
   int m_iValue00 ;
   int m_iValue01 ;
} ;

int main()
{
   MyStruct aaa, bbb, ccc ;

   std::vector aMyStruct ;

   aMyStruct.push_back(aaa) ;
   aMyStruct.push_back(bbb) ;
   aMyStruct.push_back(ccc) ;

   aMyStruct.resize(6) ; // [EDIT] double the size

   for(std::vector::size_type i = 0, iMax = aMyStruct.size(); i < iMax; ++i)
   {
      std::cout 
Комментарии (7)

Вы можете использовать тип оболочки тип элемента, с конструктор по умолчанию, который ничего не делает. Е. Г.:

template 
struct no_init
{
    T value;

    no_init() { static_assert(std::is_standard_layout::value && sizeof(T) == sizeof(no_init), "T does not have standard layout"); }

    no_init(T& v) { value = v; }
    T& operator=(T& v) { value = v; return value; }

    no_init(no_init& n) { value = n.value; }
    no_init(no_init&& n) { value = std::move(n.value); }
    T& operator=(no_init& n) { value = n.value; return this; }
    T& operator=(no_init&& n) { value = std::move(n.value); return this; }

    T* operator&() { return &value; } // So you can use &(vec[0]) etc.
};

Использовать:

std::vector vec;
vec.resize(2ul * 1024ul * 1024ul * 1024ul);
Комментарии (0)

Из вашего кода, похоже, что у вас есть вектор структур, каждая из которых состоит из 2 ИНЦ. Вы могли бы вместо этого использовать 2 векторы ИНЦ? Тогда

copy(data1, data1 + count, back_inserter(v1));
copy(data2, data2 + count, back_inserter(v2));

Теперь вы не'т платить за копирование структуры каждый раз.

Комментарии (1)

Из ваших комментариев к другим плакатам, похоже, вы'снова ушел с malloc() и друзей. Вектор выиграл'т пусть у вас есть элементы невыстроенные.

Комментарии (0)

Использовать std::вектор::резерв() метод. Он выиграл'т изменение размера вектора, но это будет выделять пространство.

Комментарии (0)

Если вы действительно настаиваете на том неинициализированные элементы и пожертвовать некоторыми методами, как передние(), назад(), push_back(), использовать импульс вектора числовых <повышение/числовой/ublas/вектор.ГЭС и GT;. Это позволяет даже не на сохранение существующих элементов при вызове размеры()...

Комментарии (0)

Сделать структуры сами должны быть в непрерывной памяти, или вы можете уйти с вектора структуры*?

Векторы сделайте копию все, что вы добавить к ним, так через векторы указателей, а не объектов-это один из способов повышения производительности.

Комментарии (1)

Я не'т думаю, что STL-это ваш ответ. Вы'вновь придется свернуть свой собственный вид решения с помощью realloc(). Вы'будете иметь, чтобы хранить указатель и размер, или количество элементов, и использовать это, чтобы найти, где начать добавлять элементы после realloc().

int *memberArray;
int arrayCount;
void GetsCalledALot(int* data1, int* data2, int count) {
    memberArray = realloc(memberArray, sizeof(int) * (arrayCount + count);
    for (int i = 0; i < count; ++i) {
        memberArray[arrayCount + i].d1 = data1[i];
        memberArray[arrayCount + i].d2 = data2[i];
    }
    arrayCount += count;
}
Комментарии (0)

Я хотел сделать что-то вроде:

void GetsCalledALot(int* data1, int* data2, int count)
{
  const size_t mvSize = memberVector.size();
  memberVector.reserve(mvSize + count);

  for (int i = 0; i < count; ++i) {
    memberVector.push_back(MyType(data1[i], data2[i]));
  }
}

Вы должны определить конструктор для типа, который хранится в memberVector, но, что'с небольшой стоимости, поскольку это даст вам лучшее из обоих миров; нет ненужных инициализации и перераспределение не произойдет во время цикла.

Комментарии (1)