Операция перемещения вектора против операции перемещения элемента

В следующем примере, почему операция векторного перемещения не запускается? Как узнать, когда следует явно использовать оператор перемещения?

#include <iostream>
#include <vector> 

using namespace std;

class Test {
  public: 
    Test() {
      std::cout << " default " << std::endl;
        
    }
    
    Test(const Test& o) {
        std::cout << " copy ctor " << std::endl;
    }
    
    Test& operator=(const Test& o) {
        std::cout << " copy assign " << std::endl;
        return *this;
    }
    
    Test(Test&& o) {
        std::cout << " move ctor" << std::endl;
    }
    
    Test& operator=(Test&& o) {
        std::cout << " move assign " << std::endl;
        return *this;
    }
};

int main()
{
  std::cout << " vector: " << std::endl;
  std::vector<Test> p;
  p = {Test()}; // expect vector move here since the RHS is temporary. 
  std::cout << std::endl;
   
  std::cout << " single value " << std::endl;
  Test tt;
  tt = Test();
}

Выход:

 vector: 
 default 
 copy ctor 

 single value 
 default 
 default 
 move assign 

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

Помните, что я сказал в вашем последнем вопросе о том, что vector отдает предпочтение согласованности, а не скорости и не использует оператор move, если вы не обещали, что это безопасно?

user4581301 17.05.2022 20:25

Рекомендую прямо указывать в вопросе, где вы ожидаете ход.

user4581301 17.05.2022 20:27

Я думаю, это потому, что когда вы помещаете Test() в фигурные скобки, он создает std::initialization_list<std::vector>, а затем копирует список инициализации в вектор и копирует каждый Test (в данном случае ваш единственный экземпляр Test) в вектор. Знает ли векторный конструктор, что нужно перемещать значения вместо копирования?

Roy Avidan 17.05.2022 20:35
p = {Test()}; использует вариант operator=( initialization_list ), а не operator=( vector&& ). Смотрите ответ в связанном вопросе. Ответ в нем должен пояснить, что говорит стандарт при использовании {...}
ChrisMM 17.05.2022 20:36

Отвечает ли это на ваш вопрос? brace-initialization boost::json::value преобразует его из объекта в массив

ChrisMM 17.05.2022 20:37
"почему операция векторного перемещения не запускается?" -- какие у вас есть доказательства того, что операция перемещения не запущена? (Одна из причин, по которой перемещение вектора является эффективным, заключается в том, что перемещение вектора не приводит к перемещению элементов, содержащихся в векторе, поэтому ваш текущий вывод не позволяет сделать окончательный вывод относительно этого перемещения.) Возможно, вы правы насчет отсутствия перемещения вектора, но в то же время , в вашем вопросе так или иначе не хватает доказательств.
JaMiT 18.05.2022 01:22
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
4
6
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

std::vector имеет оператор присваивания, который принимает std::initializer_list:

vector& operator= (initializer_list<value_type> il);

Итак, когда вы написали p = {Test()};, вы на самом деле используете приведенный выше оператор присваивания.

Теперь, почему делается вызов конструктора копирования, можно понять из dcl.init.list, в котором говорится:

An object of type std::initializer_list<E> is constructed from an initializer list as if the implementation allocated a temporary array of N elements of type const E, where N is the number of elements in the initializer list. Each element of that array is copy-initialized with the corresponding element of the initializer list, and the std::initializer_list object is constructed to refer to that array.

Другие вопросы по теме