如何初始化std :: stringstream?

时间:2014-02-21 02:34:36

标签: c++ stringstream

我需要将字符串与整数连接起来。为此,我以下列方式使用stringstream

int numPeople = 10;
stringstream ss;
ss << "Number of people is " << numPeople;

这很有效。但我试图以下面的方式做到这一点:

int numPeople = 10;
stringstream ss << "Number of people is " << numPeople;

我收到以下错误:“在'&lt;&lt;'之前的预期初始化程序令牌

为什么我收到此错误?为什么我不能在声明它的同时分配stringstream值?

2 个答案:

答案 0 :(得分:30)

stringstream ss << "Number of people is " << numPeople;
  

为什么我不能在声明它的同时分配stringstream值?

这类似于希望这可行:

int x + 3 + 9;

问题

当您同时为对象定义和赋值时,C ++允许您调用构造函数,这需要以逗号分隔的表达式列表。为方便起见,Type variable = value;符号用于调用Type variable(value);,但仅适用于单个值。

对于int,您可以轻松更正代码:

int x = 3 + 9;

...它之所以有效,是因为“3 + 9”可以先独立评估,以便在x中存储一个合理的值。 编译器对+上的运算符int的行为执行我们想要的操作:它会生成我们想要存储在int中的x结果。但是,如果您尝试stringstream ...

stringstream ss = "Number of people is " << numPeople;  // BROKEN

...它不起作用,因为"Number of people is " << numPeople需要先评估但是非法 - 你会收到类似“error C2296: '<<' : illegal, left operand has type 'const char [20]'”的错误 - 它不会给出有用的值对于stringstream构造函数。问题是编译器仍在尝试应用按位移位运算符,这只对数字有意义,因为我们想要应用的<<的重载需要类型为{{1}的左手参数}。 C ++要求在ostream&右侧评估的值与最终使用结果值进行的赋值无关地进行求值,并且此时构造的变量的类型与尝试求值的方式无关关于被分配的表达。

解决方案

这里有一个鸡与蛋的问题,因为你需要在=中组合你想要的右手值来调用stringstream的构造函数,但是为此你需要...... stringstream。实际上,您可以使用临时stringstream

来解决此问题
stringstream

不幸的是需要强制转换,因为static_cast<std::ostringstream&&>(std::ostringstream() << "Number of people is " << numPeople) 重载通过对operator<<基类的引用来处理stringstream,返回ostream,所以你需要强制转换为手动ostream&类型,以便您可以调用stringstream移动构造函数...

然后完整的单线结构......

std::stringstream

......但这太可怕而无法思考。

使解决方案(可以说)不那么可怕

根据您的敏感度,您可能会感觉到宏有帮助或更糟糕......

std::stringstream ss(static_cast<std::ostringstream&&>(std::ostringstream() << "Number of people is " << numPeople));

FWIW,您也可以使用宏来创建字符串......

#define OSS(VALUES) \
    static_cast<std::ostringstream&&>(std::ostringstream() << VALUES)

std::stringstream ss(OSS("Number of people is " << numPeople));

(可以说是)更好的做法

只需创建std::string s(OSS("Number of people is " << numPeople).str()); - 可选择为构造函数提供一个stringstream - 然后在第二个语句中使用string

operator<<

这更容易阅读。通过移动构建,在优化之后,可能没有性能原因来选择两个语句。

替代

C ++ 11引入了to_string()重载,如果你有一个或两个整数值来与std::stringstream ss; ss << "Number of people is " << numPeople; 连接或加入string,这是很方便的:

std::string s = "Number of people is " + std::to_string(numPeople);

这可能效率低下(如果你关心,请检查你的编译器优化能力):每个std::to_string()可能为独立的std::string实例动态分配一个缓冲区,然后各个连接可能涉及额外的文本复制,并且可能需要扩大原始动态分配的缓冲区,然后大多数临时std::string将需要时间在销毁期间解除分配。

在C ++ 03中更糟糕

C ++ 03缺少移动构造函数,因此有必要在临时使用std::ostringstream::str()成员函数来获取std::string的额外深层副本,用于构造命名的stringsteam 1}} ...

stringstream ss(static_cast<std::ostringstream&>(std::ostringstream() << "Number of people is " << numPeople).str());

使用这个C ++ 03代码,可能会出现重复的动态内存分配和内容副本,因此构建后跟流是更好的选择。

答案 1 :(得分:0)

必须先初始化stringbuf,然后才能将值添加到其中。 stringstream是一个对象。

通过做:

std::stringstream ss;

您实际上是允许应用程序分配空间来处理要添加的值。