При каких сценариях конструкторы перемещения вызываются для аргументов конструктора? - PullRequest
0 голосов
/ 13 апреля 2019

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

Я буду использовать некоторые примеры и сценарии из реального проекта ниже, чтобы лучше проиллюстрировать мой вопрос.

Некоторое объяснениепочему я вижу результаты этих сценариев, было бы очень полезно!

//The following code is common to all examples
//This code is the place the object creation begins
std::unique_ptr<AI::Pathfinding::cDirectedWeightedGraph> graph = std::make_unique<AI::Pathfinding::cDirectedWeightedGraph>(std::move(connections));

x ------------------------------------------------------------ x

Сценарий 1:

//Here is the actual constructor for the class
cDirectedWeightedGraph(std::vector<cConnection> i_connections) : m_connections(i_connections) {}

Результат: вызывается конструктор перемещения для класса std :: vector.

x ------------------------------------------------------------ x

Сценарий 2:

//Here is the actual constructor for the class
cDirectedWeightedGraph(std::vector<cConnection>&& i_connections) : m_connections(i_connections) {}

Результат: конструктор перемещения для класса std :: vector НЕ вызывается.

x ------------------------------------------------------------ x

Сценарий 3:

//Here is the actual constructor for the class
cDirectedWeightedGraph(std::vector<cConnection>&& i_connections) : m_connections(std::move(i_connections)) {}

Результат: вызывается конструктор перемещения для класса std :: vector.

x ------------------------------------------------------------ x

Сценарий 4:

//Here is the actual constructor for the class
cDirectedWeightedGraph(std::vector<cConnection> i_connections) : m_connections(std::move(i_connections)) {}

Result: вызывается конструктор перемещения для класса std :: vector.

x ------------------------------------------------------------ x

Замечания / Вопросы для продолжения:

  1. Кажется, не имеет значения, объявлен ли аргумент как ссылка на значение.

  2. Кроме написания конструктора перемещения или оператора присваивания перемещения для вашего класса,Вам когда-нибудь нужно использовать ссылки rvalue в вашем конструкторе?

  3. Я предполагаю, что в том месте, где вызывается конструктор, нет способа вызвать конструктор перемещения без передачи ссылки на rvalue(в любом случае это плохая практика, мне было просто любопытно).Я использую std :: move () для генерации rvalue ссылки.

1 Ответ

0 голосов
/ 13 апреля 2019

Мы знаем, что если мы вызовем std::move, то будет вызван конструктор перемещения, поэтому ожидаются 3 и 4.

Для 1, я бы сначала проверил настройки вашего компилятора, отладка не сгенерирует конструктор перемещения. Если у вас там есть оператор, использующий i_connections, вы не увидите конструктор перемещения. У clang-tidy даже есть правило, которое выявляет эти случаи и предлагает заменить 1 на 4.

Для сценария 2 компилятор решил не генерировать оптимизированный код. Вероятно, существует эвристика, которая работает немного иначе, чем в случае 1. Компилятору не нужно оптимизировать код, даже если аргумент является &&, так как он назван и, как таковой, требует вызова std::move подлежит перемещению во всех случаях.

Так что для сценариев 1 и 2 это зависит от компилятора и флага.

В конце я бы предложил использовать максимально 4, поскольку компилятор может оптимизировать ходы, если требуется, и интерфейс также совместим с копиями, если требуется.

...