C ++ 0x const rvalue riferimento come parametro funzione
-
26-10-2019 - |
Domanda
Sto cercando di capire perché qualcuno avrebbe scritto una funzione che prende un riferimento rvalue const .
Nel seguente esempio di codice quale scopo è la funzione di riferimento rvalue const (ritorno "3"). E perché preferenza risoluzione di sovraccarico const rvalue sopra la funzione const di riferimento lvalue (ritorno "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;
}
Soluzione
lvalue fortemente preferiscono il legame con lvalue riferimenti e riferimenti simile rvalue fortemente preferiscono il legame con i riferimenti rvalue. espressioni modificabili debolmente preferiscono il legame con un riferimento non-const.
Così, quando il compilatore sta facendo la risoluzione di sovraccarico, si controlla se c'è un overload che accetta un riferimento rvalue, perché è preferito fortemente. In questo caso, poiché l'experssion è un rvalue modificabile, in modo che le vittorie di sovraccarico di riferimento rvalue.
V'è in realtà utilizzare per i riferimenti rvalue const, possono essere utilizzati per assicurarsi qualcosa di non si legano a un rvalue. Si ricordi che l'rvalue si lega ad un riferimento const lvalue, quindi se avete fatto:
template <typename T> void foo(const T& bar) { /* ... */ }
E chiamato la funzione con:
foo(createVector());
Sarebbe funzionano bene. Tuttavia a volte si desidera garantire che si può passare solo lvalue ad una funzione (questo è il caso per std::ref
per uno). È possibile raggiungere questo obiettivo con l'aggiunta di un sovraccarico:
template <typename T> void foo(const T&&) = delete;
Ricordate, rvalues ??fortemente preferiscono il legame con i riferimenti rvalue, e le espressioni modificabili preferiscono debolmente legame con i riferimenti non-const. Dal momento che abbiamo un const rvalue riferimento, significa in sostanza che ogni singolo rvalue si legherà a questo, quindi, se si tenta di passare un rvalue per foo()
, il compilatore darà un errore. Questo è l'unico modo per ottenere tale funzionalità, e quindi è talvolta utile.
Altri suggerimenti
risoluzione di sovraccarico preferisce rvalue const oltre lvalue const perché, beh, è ??un rvalue e si sta legandolo ad un riferimento rvalue, ma bisogna aggiungere const in entrambi i casi, riferimento in modo rvalue sicuramente preferito.
Queste cose sono generalmente pointless- è meglio lasciarli vincolante ai sovraccarichi lvalue const. rvalues ??const non hanno alcun reale utilizzo.