从std :: stringstream传递std :: string引用作为参数

4

我正在使用std::stringstream构造一个字符串,然后试图将完成的字符串作为引用传递给一个以std::string&作为参数的函数。

在GCC上编译时出现了一个错误:

../src/so.cpp:22:21: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘std::basic_stringstream<char>::__string_type {aka std::basic_string<char>}’
../src/so.cpp:12:6: error: in passing argument 1 of ‘void myFunc(std::string&)’
make: *** [src/so.o] Error 1

这段代码可以在Windows VS2012上编译通过,但在我的Linux和Android构建中失败了。原因是什么?

我可以通过将ss.str()临时赋值给一个std::string并将该字符串作为引用传递来解决此问题,但这似乎有点愚蠢。有没有更好的正确方法?

#include <iostream>
#include <sstream>

void myFunc (std::string& msg)
{
    std::cout << msg << std::endl;
}

int main (void)
{
    std::stringstream ss;
    ss << "this is a test";

    myFunc (ss.str());              // Fails

    std::string s = ss.str();
    myFunc (s);                     // Pass

    return 0;
}

1
将警告级别设置为/W4,VS会告诉你在那一行使用了非标准扩展。 - Praetorian
4个回答

7
问题在于 myFunc 接受的是一个非 const 的左值引用。 stringstream::str() 返回一个字符串值。在标准 C++ 中,你不能将一个临时对象绑定到非 const 的左值引用上,但是 VS 有一种“扩展”可以做到这一点。这就是它能够在 VS 上编译而在其他编译器上无法编译的原因。
另一方面,const 左值引用可以绑定到右值上。因此,修改你的函数如下即可解决问题:
void myFunc (const std::string &msg) { /* as before */ }

做得很好,谢谢;很有道理。也感谢其他的回答,但我觉得这个最有用。 - Chris

4

将此更改为:

void myFunc (std::string& msg)

转换为:

void myFunc (const std::string& msg)
//           ^^^^^ this will allow temporaries like ss.str()

有些版本的Visual Studio会愚蠢地允许将临时量绑定到非const引用。然而,这是危险且无效的C++代码


1

由于您不会在myFunc内部写入字符串,因此请接受常量引用:

void myFunc (std::string const &msg)
{
  std::cout << msg << std::endl;
}

这些可以绑定到临时对象。

-1
所以你遇到这个错误的原因是,ss.str()返回的是一个const string而不是string。 通过创建一个新的字符串,你创建了一个非const变量,它被设置为与ss.str()相同的值,因此可以传递到myFunc()中。 像你现在这样创建一个新的字符串可能是最简单的修复方法,并且仍然可以使用该函数。

但是 ss.str() 不会返回一个常量字符串。 - juanchopanza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接