2010-07-12 32 views
5

下段演示我的問題:(海合會編譯錯誤)關於產品使用字符串::互換()與臨時工

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>] 

雖然我明白,STR( )在stringstream中返回一個臨時的,它沒有任何意義,並且不是直接顯而易見的,我應該用局部變量作爲參數而不是我的第一本能來調用臨時的交換。

很明顯,直接賦值效果更好,而新的C++標準具有完美的移動語義,但這些不適用於我的實現。

由於Visual Studio放寬了關於C++標準的規定,Visual Studio並沒有給出這個問題。我有點已經理解了整個const引用臨時性的東西(我認爲這是編譯錯誤的原因)。

我的問題: 任何人都可以向我解釋,如果這是唯一的解決方案,也許向我解釋如何在未來考慮這個問題,以便我可以發現和解決類似的問題?

(如果沒有人有任何偉大的見解,我至少這張貼在這裏的人有類似的問題)

+0

另一個需要注意的是,對於交換工作,必須傳入一個非const引用。我擁有的是(因爲它是一個臨時返回)一個const rvalue。所以,我明白......其他方式都是合法的(即使我明白爲什麼這樣也是合法的),但並沒有立即做出合乎邏輯的判斷。 – Marius 2010-07-12 22:09:50

+1

您是否正在編譯VS2010中的代碼,它有2個互換版本。一個參考和另一個右值參考。這可能是編譯的原因。 – Jagannath 2010-07-12 23:36:34

+0

@Jagannath:我現在正在使用VS2005,所以,唉,這些新技術都不適用於我。 – Marius 2010-07-13 16:16:06

回答

2

在已經使用的交換,以暫時性成語足夠的時間,以線條狀

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

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

這似乎不那麼格格不入。這是正常調用交換作爲臨時對象的成員函數。當然,如前所述,使用swap來填充默認構造的字符串而不是使用複製構造函數並不是那麼習慣。

+0

這最好解決了我的問題。我想我應該習慣這個成語。 – Marius 2010-09-07 14:40:25

7

您不能綁定一個臨時的非const引用。出於這個原因,從ss.str()返回的臨時文件不能傳遞給std::string::swap,該文件預計會修改其參數(因此它使用參數non-const&)。

第二個版本在你允許的臨時對象上調用成員函數時工作。

但是,爲什麼你想在第一個地方交換?通常,一個簡單的:

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

應該足夠好。這並不比swap更低效(至少在C++ 0x和move語義中),但同時更具可讀性。

+0

+1輸入比我快。 – Cogwheel 2010-07-12 22:46:55

+0

'std :: string s(s.str())'比交換慢,因爲它必須複製字符串(除了在C++ 0x中使用'&&'引用移動語義)。 – 2010-07-12 23:29:15

+0

你當然是對的,我相應地編輯了我的答案。 – hkaiser 2010-07-12 23:57:39

1

您無法將臨時參數作爲參數傳遞給swap的原因是該參數是由非const引用傳遞的。而臨時對象只能被const引用綁定。這是分佈在§8.5.3,用適當的即第5,第二個項目:

§8.5.3 A reference to type 「cv1 T1」 is initialized by an expression of type 「cv2 T2」 as follows:

  • [bullet one, does not apply here: binding to non-const ref ]

  • Otherwise, the reference shall be to a non-volatile const type (i.e., cv1 shall be const).

爲什麼在相反的方向寫調用工作的原因是,該標準允許調用臨時變異的成員函數對象。

§3.10/10 An lvalue for an object is necessary in order to modify the object except that an rvalue of class type can also be used to modify its referent under certain circumstances. [Example: a member function called for an object (9.3) can modify the object. ]

,你對未來的要求推理思路是,雖然你可以通過它自己的功能修改臨時的,你不能把它傳遞給一個函數或可能修改方法(通過非const通參考)