27

私は、なぜ誰かが定数値参照をとる関数を書くのかを理解しようとしています。

以下のコード例では、const rvalue参照関数(「3」を返す)の目的は何ですか。また、オーバーロード解決では、constLValue参照関数よりもconstRvalueが優先されるのはなぜですか(「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;
}
4

2 に答える 2

30

左辺値は左辺値参照へのバインドを強く好み、同様に右辺値参照は右辺値参照へのバインドを強く好みます。変更可能な式は、非定数参照へのバインドを弱く好みます。

したがって、コンパイラが過負荷解決を実行しているときは、右辺値参照をとる過負荷があるかどうかをチェックします。これは、それが強く推奨されるためです。この場合、式は変更可能な右辺値であるため、右辺値参照のオーバーロードが優先されます。

const右辺値参照には実際に使用され、何かが右辺値にバインドされないようにするために使用できます。右辺値は定数左辺値参照にバインドされることを忘れないでください。したがって、次のようにした場合:

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

そして、次の関数を呼び出します。

foo(createVector());

それはうまくいくでしょう。ただし、左辺値のみを関数に渡すことができるようにすることが望ましい場合があります(これは1つの場合に当てはまりますstd::ref)。これは、オーバーロードを追加することで実現できます。

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

右辺値は右辺値参照へのバインドを強く好み、変更可能な式は非定数参照へのバインドを弱くすることを好むことを忘れないでください。const rvalue-referenceがあるので、基本的にすべての右辺値がこれにバインドされることを意味します。したがって、右辺値をに渡そうとするとfoo()、コンパイラーはエラーを出します。これは、このような機能を実現する唯一の方法であるため、便利な場合があります。

于 2011-06-10T14:30:24.887 に答える
2

過負荷解決では、constlvalueよりもconstrvalueが優先されます。これは、これが右辺値であり、右辺値参照にバインドしているためですが、どちらの場合もconstを追加する必要があるため、右辺値参照が確実に優先されます。

そのようなことは一般的に無意味です-定数値のオーバーロードにバインドしたままにしておくのが最善です。constrvaluesは実際には使用されません。

于 2011-06-10T14:11:33.640 に答える