2016-07-26 9 views
2

これが私のC++構文のエラーであるかどうか、またはこれがまったく達成できないものかどうかはわかりません。std :: mapをrvalueとして作成することはできますか?

std :: mapをコンストラクタ引数として取るクラスを定義します。次に、 "一時的な"(この "rvalue"と呼ぶのに適していますか?)std :: mapを渡して、そのクラスのインスタンスを作成します。私。私はlvalue std :: mapを作成し、それをコンストラクタに渡したくありません。

これを達成できますか?私はこれが私のコンパイラです(行が失敗した試行を示しコメント)

#include <map> 
#include <string> 
#include <iostream> 

class Test 
{ 
    public: 
     Test(std::map<int,char>& rMap) 
     { 
      std::map<int,char>::iterator iter; 

      for (iter = rMap.begin(); iter != rMap.end(); ++iter) 
      { 
       mMap[iter->first] = mMap[iter->second]; 
      } 
     } 
     virtual ~Test(){} 

    protected: 
     std::map<int, char> mMap; 
}; 

int main() 
{ 
    std::cout << "Hello world!" << std::endl; 

    //Test test({1,'a'});     // Compile error. 
    //Test test(std::map<int,char>(1,'a')); // Also compile error. 
    //Test test(std::map<int,char>{1,'a'}); // Yet again compile error. 

    return 0; 
} 

を次のことを試してみました:

g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11) 

エラーは、要求に応じて投稿することができますが、彼らは有用であろう場合、私はわからないコンパイル私の問題が構文的であれば。

ありがとうございます。

+0

'テストテスト(std :: map {{1、 'a'}});' 2つの中括弧を使用しましたか? –

+0

@TimStraubinger - あなたの提案に基づいてこれを試しましたが、さらに別のコンパイルエラーが発生しました。 – StoneThrow

+0

_「コンパイルエラー」ですか? –

答えて

1
#include <map> 

class Test { 
public: 
    Test(std::map<int,char> const& cMap) 
    { 
     std::map<int,char>::const_iterator iter; 
     for (iter = cMap.cbegin(); iter != cMap.cend(); ++iter) 
     { 
      mMap[iter->first] = mMap[iter->second]; 
     } 
    } 
    virtual ~Test() { } 
protected: 
    std::map<int, char> mMap; 
}; 

int main() { 
    Test test(std::map<int,char>({{1,'a'}, {2, 'b'}})); 
    return 0; 
} 

一部の説明としてそれを使用します。それに

  1. あなたは(std::map<int,char>()のような)一時オブジェクトを渡したい場合はTest(T)Test(const T&)またはTest(T&&)コンストラクタを必要とします。 T&&コンストラクタが使用されていることを忘れないでください。疑わしい場合は、それらを使用しないでください。
  2. const std::vector/map/list/...を使用する場合は、.begin().end()を使用して要素を繰り返し処理することはできません。 c begin()と。 c end()。さらに、autoでより簡単になります。

    1)std::mapは、このコンストラクタを持っているので、この構造が利用可能である{{key, value}, {second_key, second_value}, ...} - だけではなく、

    std::map<int,char>::const_iterator iter; 
    for (iter = rMap.cbegin(); iter != rMap.cend(); ++iter) 
    
  3. {{1,'a'}, {2, 'b'}}ようstd::map使用 "をダブルブラケット" 初期化子を初期化するには

    for (auto iter = rMap.cbegin(); iter != rMap.cend(); ++iter) 
    

    を試してみてください

    map(std::initializer_list<value_type> init, 
        const Compare& comp = Compare(), 
        const Allocator& alloc = Allocator()); 
    // see http://en.cppreference.com/w/cpp/container/map/map 
    

    2)内括弧{1,'a'}は、value_typeコンストラクタコールとして解釈されます。 std::map<int, char>value_typestd::pair<int, char>です。

P. S. std::map<int,char>()std::map<int,char>{}コンストラクタの呼び出しが同じであることを忘れないでください。 std::map<int,char>({{1,'a'},{2,'b'}}) --> std::map<int,char>{{1,'a'},{2,'b'}}あなたが使用する必要があります

+2

私はあなたの散文とあなたの例がほぼ正反対のことを言うのが好きです。 –

+0

@LightnessRacesinOrbitまあ、質問者はコンストラクタでr値を受け入れたいと思っていました。私の例は著者の質問を解決しますが、私は著者がr値が使われるべき意味を理解しているのかと疑問に思っています。 – slavanap

+1

あなたは、この答えがその理解を増やす可能性が高いとお考えですか? –

4

はい、コンストラクタは左辺値参照を受け取ります。代わりに、参照番号const、またはrvalue参照にする必要があります。

他のタイプとまったく同じです。

+0

const(参照値とは対照的に)への参照を使用したい場合、正しい構文は何ですか?コンストラクタTest(std :: map const&rMap)を定義した後、私はrvalue std :: mapインスタンスでこれを呼び出すことにまだ苦労しています。 – StoneThrow

+0

@StoneThrow:「私は苦労している」とはどういう意味ですか? –

+0

ここで「苦労している」とは、継続してコンパイルエラーが発生したことを意味します。コンストラクタをTest(std :: map const&rMap)に変更しても、main()の3つのメソッドのいずれかを使用してTestオブジェクトをインスタンス化できません。コンストラクタがconstへの参照を取得した場合、Testオブジェクトに_instantiate_する正しい構文は何ですか? – StoneThrow

5

一時以外のconst L値の参照にバインドすることはできません

Test(std::map<int, char> rMap) : mMap(std::move(rMap)) {} 

または

Test(std::map<int, char>&& rMap) : mMap(std::move(rMap)) {} 

または

Test(const std::map<int, char>& rMap) : mMap(rMap) {} 

を行います。

そして

Test test({{1,'a'}}); 
Test test2({{1,'a'}, {2, 'b'}}); 
+3

_Why?_説明なしでは役に立たない。コードダンプだけではありません。 –

+0

@ Jarod42オプション1を使用した場合、Testオブジェクトをインスタンス化する正しい方法は何ですか?私はまだrvalue std :: mapを作成する構文に問題があります。 – StoneThrow

0

:それはあなたがフロントブラケットをドロップすることができることを意味し

class Test 
{ 
public: 
    Test(const std::map<int,char>& rMap) : mMap(rMap) 
    {} 
    Test(std::map<int,char>&& rMap) : mMap(std::move(rMap)) 
    {} 
    virtual ~Test(){} 
protected: 
    std::map<int, char> mMap; 
}; 

これは、2つのコンストラクタ提供:mMapと右辺値参照を取る一つにconst左辺値参照とコピーの内容を取得1をとそのコンテンツをmMapに移動します。これは、あなたはstd::mapという名前または一時的のいずれか使用してTestインスタンスを作成することができます:

int main() 
{ 
    std::map<int,char> m{{1, 'a'}, {2,'b'}}; 
    Test t1{m}; 
    Test t2{{{1, 'a'}, {2, 'b'}}}; 
} 

これは、ときにすることができますが、不要なコピーを避けることができますが、それでも必要なときにmapのコピーを作成することができます。

+0

確かにそれを行う方法は、マップを値でとる単一のオーバーロードですか? –

+0

@LightnessRacesinOrbit人々(Nieblerなど)はそれを言っていますが、それが余分な動きを起こさなかった場合は素晴らしいでしょう。 – Barry

+0

@Barry:移動は、最適化できない場合でも効果的です(これはまれです)。これが本当に問題であるいくつかの状況がなければ、あなた自身を繰り返すよりもはるかに優れています。 –

関連する問題