我一直在使用以下代码清除std::stringstream
:
m.swap(std::stringstream());
代码可能取自this SO thread。最近我在Visual Studio 2013中编译了代码,收到了以下警告:
warning C4239: nonstandard extension used : 'argument' : conversion from 'std::basic_stringstream<char,std::char_traits<char>,std::allocator<char>>' to 'std::basic_stringstream<char,std::char_traits<char>,std::allocator<char>> &'
1> A non-const reference may only be bound to an lvalue
我在使用/ W4的早期版本的Visual Studio中没有收到任何警告。我记得在早期版本中我无法可靠地清除字符串流,这就是我最初使用该代码的原因。
因此可以通过这种方式清除字符串流,如果没有,你可以解释原因吗?还有一种可移植的方式来清除字符串流吗?感谢
编辑:这是请求的代码。使用/W4
进行编译以查看警告。
int _tmain(int argc, _TCHAR* argv[])
{
std::stringstream m;
m.swap(std::stringstream());
return 0;
}
答案 0 :(得分:4)
这里是std::stringstream::swap()
的签名:
void swap( basic_stringstream& other );
如您所见,swap()
对其参数采用左值引用。正如编译器正确告诉您的那样,右值或临时值无法绑定到左值引用。有些编译器支持允许你这样做的非标准扩展,但我建议你保持在标准的范围内,它会更安全。
但是,虽然您可能无法将临时值绑定到左值引用,但您可以使用此std::skipws
技巧将转换临时值:
m.swap(static_cast<std::stringstream&>(stringstream{} >> std::skipws));
甚至
std::stringstream{}.swap(m):
在第一个示例中,函数operator>>()
返回对流的引用,可以安全地与swap()
一起使用,因为保存参数的引用在函数末尾被销毁。 / p>
答案 1 :(得分:1)
std::swap
函数需要两个非const 参数进行交换。这是因为调用函数时会更改这两个参数。同样,std::stringstream::swap(...)
函数只需要一个非const 参数进行交换。
例如:
std::vector<int> vec1, vec2;
std::swap(vec1, vec2);
在上面的示例中,vec1
和vec2
都被更改了。当你尝试这样做时......
m.swap(std::stringstream());
...您正试图将临时std::stringstream()
的内容分配给m
的内容,这对编译器来说就像一个bug,即使您的意图只是为了清除m
的内容。
要删除警告,只需在执行交换之前声明临时std::stringstream
。像这样:
std::stringstream temp;
m.swap(temp);
答案 2 :(得分:1)
标准不允许使用swap
。宣言是
template <typename CharT, typename Traits, typename Allocator>
void std::basic_stringstream<CharT, Traits, Allocator>::swap(
basic_stringstream& other);
这意味着将修改两个stringstream
个对象。但是表达式std::stringstream()
是一个右值(特别是一个临时的),并且C ++不允许将非常量左值引用绑定到临时值,因为修改临时值通常不是真正的意图。
简单的解决方案是:
m = std::stringstream();
但是如果你需要支持没有C ++ 11支持的编译器,那么两者都不会起作用,因为在C ++ 03标准中,stringstream
没有swap
函数而没有公共{{1} }。在这种情况下,您需要使用:
operator=