Конструктор копирования выбран поверх конструктора перемещения при возврате нестатического c локального объекта - PullRequest
1 голос
/ 14 июля 2020

Раньше я предполагал, что конструкторам перемещения класса будет отдан приоритет над конструкторами копирования, но в приведенном ниже коде кажется, что конструктор копирования выбран, даже если объект должен быть перемещаемым.

Do вы понимаете, почему нижеприведенные коды выбирают конструктор копирования, когда foo() возвращает vector<B> B?

#include <iostream>
#include <vector>

using namespace std;

class B {
public:
  int var_;

  B(int var) : var_(var)
  {
    cout << "I'm normal" << endl;
  }

  B(const B& other)
  {
    cout << "I'm copy constructor" << endl;
  }

  B(B&& other)
  {
    cout << "I'm move constructor" << endl;
  }
};

vector<B> foo()
{
  vector<B> b;

  b.push_back(1);
  b.push_back(2);

  return b;
}

int main()
{
  vector<B> b {foo()};
}

Результат такой, как показано ниже.

$ g++ main.cpp
$ a.out
I'm normal
I'm move constructor
I'm normal
I'm move constructor
I'm copy constructor

Любопытно, если я удалю его в строке foo() вместо этого выбирается конструктор перемещения:

vector<B> foo()
{
  vector<B> b;

  b.push_back(1);

  return b;
}

Теперь результат такой, как показано ниже:

$ g++ main.cpp
$ a.out
I'm normal
I'm move constructor

1 Ответ

3 голосов
/ 14 июля 2020
• 1000 * будет превышено, чтобы соответствовать амортизированной постоянной сложности, требуемой стандартом.

Теперь компилятор может выбрать конструктор перемещения для перераспределения, только если он помечен как noexcept. Чтобы использовать конструктор перемещения вектора, объявите его следующим образом:

B(B&& other) noexcept
{
//
}

Вы можете полностью удалить перераспределение, предварительно зарезервировав место:

vector<B> foo()
{
  vector<B> b;
  b.reserve(2);
  b.push_back(1);
  b.push_back(2);

  return b;
}

Или инициализировав вектор за один go:

vector<B> foo()
{
  return vector<B>{1, 2};
}
...