При добавлении элемента в вектор, как узнать, что будет сделана копия объекта? - PullRequest
1 голос
/ 17 декабря 2011

У меня есть объект с именем LastQueryInfo lastQuery в моем классе.Каждый раз, когда этот объект изменяется, я добавляю его в вектор с именем history.

. Первоначально, когда я сделал history.push_back(lastQuery), я не знал, что произойдет, - собирается ли вектор сделать копиюобъект?или это будет держать ссылку на это?Поэтому, если позже я изменю lastQuery, будут ли изменены все объекты (если они являются ссылками) в векторе истории?

После некоторого тестирования я обнаружил, что history.push_back(lastQuery) действительно собирается сделать копиюобъект, затем добавьте его в вектор.Но как я могу знать это, не выполняя никаких тестов?Как я могу узнать, когда C ++ собирается сделать копию, и когда он собирается добавить фактический объект?

Ответы [ 2 ]

7 голосов
/ 17 декабря 2011

std::vector всегда хранит копию того, что вы push_back().Поэтому изменение переданного вами значения не повлияет на значение, хранящееся в векторе.Это не похоже на Java или C #, где Object o; на самом деле является ссылкой на объект, и объект живет до тех пор, пока не придет сборщик мусора и не поднимет его, когда последняя ссылка на него исчезнет.В C ++ Object o; - это фактический объект , который исчезнет в конце своей области видимости.

Так что, если std::vector хранит только ссылки на объекты, которые вы push_back(),тогда это будет совершенно бесполезно для таких вещей:

std::vector<int> numbers;
for(/* loop condition */) {
    int number = GetUserInput();
    numbers.push_back(n);
}

Поскольку number исчезнет в конце цикла, numbers будет содержать ссылки на то, чего не будет, если std::vectorбыл реализован путем хранения только ссылок.Если std::vector действительно хранит значения, вы можете получить к ним доступ даже после цикла.

C ++ 11 поддерживает семантику перемещения , так что если вы«Откат» на самом деле является временным, который скоро уйдет, он будет перемещать внутренности объекта в векторное хранилище вместо копирования.Вы также можете явно использовать C ++ 11 std::move(), чтобы «форсировать» движение во время push_back().Но вектор будет копировать значение в любом другом случае.Это деталь реализации для оптимизации производительности векторов.

4 голосов
/ 17 декабря 2011

Использование push_back всегда создает копию сохраняемого объекта.

Если вы используете c ++ 11, то существует два способа избежать копирования:

  • используйте метод emplace
  • , чтобы переместить созданный объект в вектор: vec.push_back( std::move( obj ) );

Если вы не используете c ++ 11,тогда единственное, что вы можете сделать, это использовать указатели или boost::shared_ptr в качестве векторных типов.

...