以下部分演示了我的问题:( 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()返回一个临时的,但它没有意义,并且我不应该立即明白我应该使用局部变量作为参数而不是我的第一直觉来调用临时交换。 / p>
显然,直接赋值工作效果更好,而较新的C ++标准已经移动了语义,这是完美的,但这些并不适用于我的实现。
Visual Studio没有给出这个问题,因为它对C ++标准感到放松。我有点已经理解了对临时事物的整个const引用(我假设是编译错误的原因)。
我的问题: 任何人都可以向我解释这是否是唯一的解决方案,或许可以向我解释将来如何考虑这个问题,以便我能发现并解决类似的问题?
(如果没有人有任何有用的见解,我至少会在这里为有类似问题的人发帖)
答案 0 :(得分:7)
您不能将临时绑定到非const引用。因此,从ss.str()
返回的临时值无法传递给期望修改其参数的std::string::swap
(因此它使用non-const&
来获取其参数。)
第二个版本适用于您在允许的临时对象上调用成员函数。
但你为什么要先换掉?通常,简单:
std::string s(ss.str());
应该足够好。这并不比交换效率低(至少在带有移动语义的C ++ 0x中),但同时更具可读性。
答案 1 :(得分:2)
在使用了与临时习惯交换的习惯之后,用
这样的行std::vector<int>().swap(v); // clear and minimize capacity
或
std::vector<int>(v).swap(v); // shrink to fit
这似乎不太合适。将swap作为临时对象的成员函数调用 normal 。当然,如前所述,使用swap来填充默认构造的字符串而不是使用复制构造函数并不是那么惯用。
答案 2 :(得分:1)
您无法将临时参数传递给swap
的原因是该参数是由非const引用传递的。临时工具只能被const引用绑定。这分布在§8.5.3中,适当的存在于第5段,第二个子弹:
§8.5.3对类型“cv1 T1”的引用由类型为“cv2 T2”的表达式初始化,如下所示:
[bullet one,此处不适用:绑定到非const ref]
否则,引用应为非易失性const类型(即cv1应为const)。
在相反方向编写调用的原因是标准允许在临时对象上调用变异成员函数。
§3.10/ 10为了修改对象,对象的左值是必要的,除了在某些情况下也可以使用类类型的右值来修改它的指示对象。 [示例:调用对象(9.3)的成员函数可以修改对象。 ]
您要求未来的推理线是,虽然您可以通过它自己的函数修改临时,但您不能将它传递给可以修改它的函数或方法(通过非const引用传递)