2017-02-14 1 views
1

Что такое быстрый/эффективный способ инициализации с данными a std::vector переменная-член в классе?Наиболее эффективный способ инициализации вектора-члена элемента с большим набором данных

Вот что я смог придумать:

class LargeClass 
{ 
//lot of data, with long running constructor to initialize them 
} 

class EngineClass 
{ 

public: 
EngineClass(const vector<LargeClass>& vectorOfLargeClass) 
{ 
mVectorOfLargeClass = vectorOfLargeClass; //Here is what I was able to come up 
} 

private: 
vector<LargeClass> mVectorOfLargeClass; 

} 

int main() 
{ 
vector<LargeClass> vectorOfLargeClass; 
... 
//fill vectorOfLargeClass with a lot of data 
... 
EngineClass engine(vectorOfLargeClass); 
... 
} 

мне нужно EngineClass держать копию данных vectorOfLargeClass вектора, который был создан в main().

Я использую C++ 11, но я не полностью знаком с языком, и, возможно, есть более стандартный способ выполнения такой задачи.

+1

сделать вам нужно сделать * копия * или вы можете * переместить * то, что вы уже создали? – vu1p3n0x

+0

Мне действительно интересно как двигаться, так и копировать. Перемещение происходит быстрее, чем копия, указанная выше? – Avithohol

+1

@Avithohol по определению, нет копии, если вы * переместите *, так что .. да. Ничто не бесконечно быстрее чем-то = P – WhozCraig

ответ

4

Вы можете сделать:

class EngineClass 
{ 
public: 
    EngineClass(vector<LargeClass> vectorOfLargeClass) : 
     mVectorOfLargeClass(std::move(vectorOfLargeClass) {} 

private: 
    vector<LargeClass> mVectorOfLargeClass; 
}; 

Таким образом, вы можете переместить или скопировать вектор:

EngineClass engine(vectorOfLargeClass); // copy 
EngineClass engine(std::move(vectorOfLargeClass)); // move 
+0

что касается ** своп **? Будет ли это быстрее, чем ** переместить **? – Avithohol

+1

swap будет примерно таким же, как и перемещение, потому что 'std :: swap' должен перемещаться, если у него есть опция – vu1p3n0x

+1

@Avithohol Нет, не было заметно. – Yakk

1

Чуть более быстрый способ будет использовать список инициализации конструктора, чтобы инициализировать переменные-члены:

EngineClass(const vector<LargeClass>& vectorOfLargeClass) 
: mVectorOfLargeClass(vectorOfLargeClass) 
{ 
} 

Как правило, предпочитают инициализировать переменные-члены в списке инициализации конструктора.

Если вы не хотите копировать входной вектор, а переносите его в векторе-члене, вы можете использовать функцию-член std::vector::swap, которая является супер быстрой, поскольку она эквивалентна обмену указателями, чтобы обменять буферы между векторами :

EngineClass(vector<LargeClass>& vectorOfLargeClass) 
{ 
    mVectorOfLargeClass.swap(vectorOfLargeClass); 
} 
+1

Почему это немного быстрее? – Jonas

+1

@Jonas Быстрее, потому что вы инициализируете вектор-член после его рождения. В противном случае сначала создается конструктор вектора (т. Е. Создается вектор-член), а затем вы вызываете оператор присваивания элемента вектора для копирования элементов. Это включает в себя больше вызовов функций, что делает его бит litle более медленным. – 101010

+1

Хорошая точка. Может ли компилятор оптимизировать вызов первого конструктора? – Jonas

6

Добавить шаг конструктор:

EngineClass(vector<LargeClass>&& vectorOfLargeClass) : 
    mVectorOfLargeClass(std::move(vectorOfLargeClass)) 
{ 
} 

затем использовать его следующим образом:

EngineClass engine(std::move(vectorOfLargeClass)); 

, но это предполагает, что vectorOfLargeClass не после того, как std::move больше не нужен в main

+1

Принуждение к переходу - интересный вариант, но вы должны скорее оправдать, чем просто оставить его там. – Yakk

+0

Я не получаю здесь двойной оператор ссылки ... означает ли это, что ссылка на указатель берется и передается в std :: move? – Avithohol

+1

@Avith '&&' как модификатор типа означает «rvalue reference» или «ссылку на что-то, что вы можете рассматривать как временное и украсть его состояние, безопасно перемещаясь». Это всего лишь ссылка, но та, которая привязана к временным ресурсам в записи, доступной для записи, или из объектов, переданных через 'std :: move', чтобы выглядеть временным. Узнайте о перемещении и rvalues ​​в C++ 11. – Yakk

Смежные вопросы