5

次のセグメントは私の問題を示しています:(GCCでのコンパイルエラー)

stringstream ss;
string s;
ss << "Hello";

// This fails:
// s.swap(ss.str());

// This works:
ss.str().swap(s);

私のエラー:

constSwap.cc:14: error: no matching function for call to 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >::swap(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
basic_string.tcc:496: note: candidates are: void std::basic_string<_CharT, _Traits, _Alloc>::swap(std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]

stringstreamのstr()が一時的なものを返すことは理解していますが、それは意味がなく、最初の本能ではなく、ローカル変数をパラメーターとして使用して一時的なもののスワップを呼び出す必要があることはすぐにはわかりませんでした。

明らかに、ストレート割り当ての方がうまく機能し、新しいC ++標準には完璧な移動セマンティクスがありますが、これらは私の実装では利用できません。

Visual Studioは、C ++標準について緩和されているため、この問題は発生しません。私は、一時的なものへのconst参照全体をすでに理解しています(これが私のコンパイルエラーの理由であると思います)。

私の質問:これが唯一の解決策であるかどうかを誰かに説明してもらえますか?また、同様の問題を見つけて回避できるように、将来これについて考える方法を説明してもらえますか?

(誰も素晴らしい洞察を持っていない場合、私は少なくとも同様の問題を抱えている人々のためにこれをここに投稿しています)

4

3 に答える 3

7

一時的なものを非定数参照にバインドすることはできません。このため、パラメータを変更することを期待しているfromに一時的に返さss.str()れるものを渡すことはできませんstd::string::swap(したがって、を使用して引数を取りますnon-const&)。

2番目のバージョンは、許可されている一時オブジェクトでメンバー関数を呼び出しているときに機能します。

しかし、なぜそもそも交換したいのですか?通常、単純です。

std::string s(ss.str());

十分に良いはずです。これはスワップよりも効率的ではありませんが(少なくとも移動セマンティクスを備えたC ++ 0xでは)、同時にはるかに読みやすくなります。

于 2010-07-12T22:44:12.993 に答える
2

一時的な交換のイディオムを十分な回数使用した後、次のような行で

std::vector<int>().swap(v); // clear and minimize capacity

また

std::vector<int>(v).swap(v); // shrink to fit

これはそれほど場違いではないようです。一時オブジェクトのメンバー関数としてswapを呼び出すのは通常のことです。もちろん、すでに述べたように、コピーコンストラクターを使用する代わりに、スワップを使用してデフォルトで構成された文字列を入力することはそれほど慣用的ではありません。

于 2010-07-12T22:53:02.940 に答える
1

一時を引数として渡すことができない理由swapは、引数が非定数参照によって渡されるためです。また、一時的なものはconst-referencesによってのみバインドできます。これは§8.5.3にまたがっており、適切なものはパラグラフ5の2番目の箇条書きにあります。

§8.5.3タイプ「cv1T1」への参照は、タイプ「cv2T2」の式によって次のように初期化されます。

  • [箇条書き1、ここでは適用されません:non-constrefへのバインド]

  • それ以外の場合、参照は不揮発性constタイプになります(つまり、cv1はconstになります)。

反対方向に呼び出しを書き込むことが機能する理由は、標準では一時オブジェクトの変更メンバー関数を呼び出すことができるためです。

§3.10/10オブジェクトを変更するには、オブジェクトの左辺値が必要です。ただし、特定の状況下でクラスタイプの右辺値を使用して、その指示対象を変更することもできます。[例:オブジェクト(9.3)に対して呼び出されたメンバー関数は、オブジェクトを変更できます。]

将来に要求する理由は、一時的なものはそれ自体の関数を介して変更できますが、それを変更できる関数またはメソッドに渡すことはできないということです(非定数参照を渡す)

于 2010-07-12T23:24:50.323 に答える