2016-05-24 6 views
1

STLコンテナ内の定数(または定数ではない)参照をどのように渡して操作しますか。C++で関数引数としてreference_wrapperオブジェクトを渡す

bool foo(const Obj& A, const Obj& B) { 
    // do some computation on A & B 
} 

と& Bは常に一緒に発生するので、私はSTLのペアに入れたい:私は機能を持っていると言う

bool foo(const std::pair<Obj, Obj>& A_and_B) { 
    // do some computation on A & B 
} 

しかし、今の両方が& Bはにコピーされますオブジェクトfooを呼び出す必要があるたびにペアを作成します。私はreference_wrapperをC++ 11で見つけました。このようなことはうまくいかないが、ポインタを使わずに参照値でコンテナを渡す正しい方法は何ですか?

+0

"正しい"方法はありませんが、仮引数型を 'pair const&'または 'pair const'とすることです。 –

答えて

-1

参照によってペアを渡すので、コピーされません。ただし、Obj A=A_and_B.firstはコピーを作成します。それを避けたい場合は、要素への参照を得ることができます。つまり、

Obj &A=A_and_B.firstです。

+0

私はdownvoteを気にしませんが、私は私の答えで間違っているものについて興味があります..? – nikaza

+0

Obv my_A = A_and_B.firstがOPのコードに(現在)存在していないので、私はdownvoterではありませんが、おそらく、ですか? –

+0

@Cheersとhth。 - Alf Heh、nice point、修正済み、ありがとう:) – nikaza

1

make_pairのコピーを避けるには、ペアをstd::pair<Obj&, Obj&>と直接定義してみましょう。

#include <iostream> 
#include <string> 
#include <functional> 
class Obj 
{ 
}; 

bool foo(const std::pair<Obj, Obj>& A_and_B) { 
    // do some computation on A & B 
    std::cout << __func__ << std::endl; 
} 

bool foo(const std::pair<Obj&, Obj&>& A_and_B) { 
    // do some computation on A & B 
    std::cout << "ref version foo" << std::endl; 
} 

int main(void) 
{ 
    Obj A; 
    Obj B; 
    foo(std::make_pair(std::ref(A), std::ref(B))); 
    return 0; 
} 
+0

最初のオーバーロードを削除し、2番目の「const」への参照への参照を変更したいとします。 –

0

std::make_pair支持体には、セマンティクスを移動するので、あなたはちょうどあなたが示唆したように、あなたの関数を記述する必要がありますが、呼び出すときに、以下のように、それはstd::make_pairにオブジェクトABを移動

// Just as you already suggested 
bool foo(const std::pair<Obj, Obj>& A_and_B) { 
    // do some computation on A & B 
} 

コールそれは:

int main(void) 
{ 
    Obj A; // work on A 
    Obj B; // work on B 
    auto A_and_B = std::make_pair(std::move(A), std::move(B)); // effectively moves A and B; no copies! 
    // A and B are now reset, but you can use A_and_B.first and A_and_B.second! 
    foo(A_and_B ); 
    return 0; 
} 

Live demo.

+0

OPが引数オブジェクトを動かすことはほとんどありません。 –

+0

@ Cheersandhth.-Alf誰もが混乱していると思われ、 'reference_wrapper'を使用することは良い証拠です。私はOPが不要なコピーを作らずにAとBを結びつけたいと思う。 –

+0

私はこのコメントに同意します。モジュロs/everyone/everyone/g。しかし、移動は答えではありません。なぜなら、移動可能な型の移動(1)は実際の引数を変更します。これは望ましくありません。また、(2)移動不可能な型はコピーになります。参照のペアを渡すとうまくいきます。 ;-) –

1

は、ここで参照のちょうどペア(なしコピー)を渡して、一つの方法です:std::make_pairは、その後のタイプと呼ばへの参照を推測、std::reference_wrapper引数のための特別なサポートを持っているので

#include <utility>   // pair 
#include <functional>  // ref 
#include <iostream> 
using namespace std; 

struct Obj {}; 

auto foo(pair<Obj const&, Obj const&> const ab) 
{ 
    Obj const& a = ab.first; 
    Obj const& b = ab.second; 
    cout << &a << " " << &b << endl; 
} 

auto main() -> int 
{ 
    Obj a; 
    Obj b; 
    cout << &a << " " << &b << endl; 
    foo(make_pair(ref(a), ref(b))); 
} 

これはうまく動作します。

std::reference_wrapperの結果タイプはstd::refです。

+0

私はこれが好きです、私はそれが最もきれいな提案だと思います。 – nikaza

関連する問題