Вопрос

Я пытаюсь понять, почему кто-то написал функцию, которая принимает ссылка на константное значение.

В приведенном ниже примере кода для какой цели является ссылочная функция const rvalue (возвращающая «3»).И почему разрешение перегрузки отдает предпочтение const Rvalue над ссылочной функцией const LValue (возвращающей «2»).

#include <string>
#include <vector>
#include <iostream>

std::vector<std::string> createVector() { return std::vector<std::string>(); } 

//takes movable rvalue
void func(std::vector<std::string> &&p) { std::cout << "1"; }

//takes const lvalue
void func(const std::vector<std::string> &p)  { std::cout << "2"; }

//takes const rvalue???
//what is the point of const rvalue? if const I assume it is not movable?
void func(const std::vector<std::string> &&p) { std::cout << "3"; }

int main()
{
    func(createVector());
    return 0;
}
Это было полезно?

Решение

Lvalues ​​настоятельно предпочитают привязку к ссылкам lvalue, и аналогичным образом ссылки rvalue предпочитают привязку к ссылкам rvalue.Изменяемые выражения слабо предпочитают привязку к неконстантной ссылке.

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

На самом деле существуют ссылки на const rvalue, их можно использовать, чтобы что-то убедиться не привязать к значению r.Помните, что rvalue привязывается к константной ссылке lvalue, поэтому, если вы это сделали:

template <typename T> void foo(const T& bar) { /* ... */ }

И вызвал функцию с помощью:

foo(createVector());

Это сработает нормально.Однако иногда желательно гарантировать, что вы можете передавать в функцию только lvalue (это случай std::ref для одного).Вы можете добиться этого, добавив перегрузку:

template <typename T> void foo(const T&&) = delete;

Помните, что rvalue предпочитают привязку к ссылкам rvalue, а изменяемые выражения предпочитают слабую привязку к неконстантным ссылкам.Поскольку у нас есть константная ссылка на значение rvalue, это в основном означает, что каждое отдельное значение rvalue будет привязано к этому, поэтому, если вы попытаетесь передать значение rvalue в foo(), ваш компилятор выдаст ошибку.Это единственный способ добиться такой функциональности, и поэтому иногда он бывает полезен.

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

Разрешение перегрузки предпочитает const rvalue, а не const lvalue, потому что, ну, это rvalue, и вы привязываете его к ссылке на rvalue, но вам нужно добавить const в обоих случаях, поэтому ссылка на rvalue определенно предпочтительнее.

Такие вещи, как правило, бессмысленны — лучше всего оставить их привязку к перегрузкам const lvalue.Константные значения не имеют никакого реального применения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top