Передача вектора с сигнатурой функции std :: move - PullRequest
5 голосов
/ 20 января 2020

Рассмотрите код ниже

void foo(std::vector<int> v)
{
   //do something here
}
//calling the function
vector<int> v1 = {1,2,3};
foo(std::move(v1));

Мой вопрос: разве функция foo не должна иметь сигнатуру void foo(std::vector<int>&& v), чтобы она могла принимать ссылку на значение r вектора?

Ответы [ 3 ]

6 голосов
/ 21 января 2020

Мой вопрос: разве функция foo не должна иметь сигнатуру void foo(std::vector<int>&& v), чтобы она могла принимать ссылку на значение r вектора?

Если это то, что вам нужно тогда да, но это не значит, что у вас неправильно. Когда вы передаете что-то функции, функция copy инициализирует параметр из источника. Это означает, что если вы сделаете

vector<int> v1 = {1,2,3};
foo(v1);

, то foo получит копию v1. С помощью

vector<int> v1 = {1,2,3};
foo(std::move(v1));

Мы копируем инициализацию v из std::move(v1), и поскольку std::move(v1) является ссылкой на значение, конструктор перемещения выбран для v, и v1 перемещается в функцию.

Таким образом, принимая по значению, вы даете возможность вызывающей стороне дать ему временную ссылку, ссылку на значение rvalue, которая одновременно переместит объект в функцию или просто позволит выполнить копирование. Если бы у вас было void foo(std::vector<int>&& v), то вы могли бы передать только временное или std::move() значение. Не было бы возможности позволить вызывающей стороне сделать копию, не создавая ее самостоятельно, а затем перемещая эту копию в функцию.

2 голосов
/ 21 января 2020

Разве функция foo не должна иметь сигнатуру void foo(std::vector<int>&& v), чтобы она могла принимать ссылку на значение r вектора?

Это std::vector<int> ' Переместите конструктор с такой подписью.

Функция foo() принимает в качестве аргумента std::vector<int> объект по значению :

void foo(std::vector<int> v) {
   // ...
}

Параметр объект v должен быть как-то построен. Аргумент , переданный foo(), используется для создания этого объекта параметра.

Вызывая foo(), как в выражении foo(std::move(v1)), объект параметра в foo(), v, построено движение . Это отличается от вызова foo(), как в выражении foo(v1), что приводит к тому, что объект параметра v представляет собой копию, созданную .

Следовательно, это конструктор перемещения объекта параметра (т. Е. v, std::vector<int> объект), который принимает std::vector<int>&&.

1 голос
/ 21 января 2020
void foo(std::vector<int> v)

Означает, что функция принимает в качестве параметра объект std::vector<int> . Вызывающий может построить этот параметр объекта, как ему угодно, но затем он принадлежит и используется foo.

В вызывающем абоненте у вас есть:

foo(/**compiler constructs the v parameter from whatever is here**/);

Следовательно:

vector<int> v1 = {1,2,3};
foo(v1); // This constructs the parameter `v` as a copy of `v1`.

По сравнению с

vector<int> v1 = {1,2,3};
foo(std::move(v1)); // This constructs the parameter `v` by moving from the value of `v1`.

Любой из них действителен, но они немного отличаются друг от друга.


void foo(std::vector<int>&& v)

Означает, что функция принимает ссылку в качестве параметра, который ссылается на std::vector<int>, который находится в другом месте, а также означает, что вызывающая сторона не должна использовать параметр после того, как эта функция выполнена с ним, так как вызывающая сторона намеревается лишить законной силы некоторым способом.

Язык помогает предотвратить ошибки, либо

  • , заставляя вас либо пропустить временный (поэтому вызывающий не может случайно попытаться использовать значение, на которое ссылается vector после foo завершено),
  • или вынуждает вас вызвать std::move, чтобы пообещать компилятору, что вы не будете пытаться использовать значение, на которое указывает ссылка vector после завершения foo)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...