C ++ 0x const RValue ссылка в качестве параметра функции - PullRequest
27 голосов
/ 10 июня 2011

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

В приведенном ниже примере кода для какой цели используется ссылочная функция const rvalue (возвращающая «3»). И почему разрешение перегрузки предпочтение Конст 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;
}

Ответы [ 2 ]

30 голосов
/ 10 июня 2011

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

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

На самом деле есть использование для константных ссылок на rvalue, они могут быть использованы, чтобы убедиться, что не не связывается с rvalue. Помните, что rvalue связывается с константной lvalue ссылкой, следовательно, если вы это сделали:

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

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

foo(createVector());

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

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

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

2 голосов
/ 10 июня 2011

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

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

...