如何初始化std :: stringstream? [英] How to initialize a std::stringstream?

查看:362
本文介绍了如何初始化std :: stringstream?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要用整数连接字符串.为此,我以以下方式使用 stringstream :

I need to concatenate a string with integers. To do that I'm using stringstream in the following way:

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

那行得通.但是我试图通过以下方式做到这一点:

And that worked. But I was trying to do it in the way below:

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

我收到以下错误:"在'<<'之前的预期初始化程序令牌"

And I was getting the following error: "expected initializer before '<<' token"

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

Why was I getting this error? Why can't I assign the stringstream value at the same time I declare it?

推荐答案

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

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

这类似于希望它能起作用:

This is similar to hoping this would work:

int x + 3 + 9;

问题

在定义和给对象赋值时,C ++允许您调用构造函数,该构造函数需要用逗号分隔的表达式列表.为了方便起见,省略了 Type variable = value; 表示法来调用 Type variable(value); ,但仅适用于单个值.

The problem

When you're both defining and giving a value to an object, C++ lets you call the constructor, which requires a comma-separated list of expressions. For convenience the Type variable = value; notation is elided to call Type variable(value);, but only works for a single value.

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

For int, you can easily correct the code:

int x = 3 + 9;

...它之所以有效,是因为可以先对"3 + 9"进行独立评估,以给出一个合理的值存储在 x 中. int s上操作符 + 的编译器行为完成了我们想要的:它生成了我们随后想要的 int 结果存储在 x 中.但是,如果您尝试使用 stringstream ...

...and it works because "3 + 9" can be evaluated independently first to give a sane value to store in x. The compiler's behaviour for operator + on ints does what we want: it produces the int result we then want to store in x. But if you try that for stringstream...

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

...这是行不通的,因为人数为"<<首先需要对numPeople 求值,但它是非法的-您会收到类似" error C2296:'<<'"的错误:非法,左操作数的类型为'const char [20]'-它不会为 stringstream 构造函数提供有用的值.问题在于,编译器仍在尝试应用按位移位运算符,该运算符仅对数字有意义,因为我们要应用的<< 的重载需要一个左手参数类型为 ostream& .C ++要求在 = 右边评估的值独立于最终用结果值完成的赋值进行评估,并且此时构造的变量的类型与方法无关.尝试对分配的表达式求值.

...it won't work, because "Number of people is " << numPeople needs to be evaluated first but is illegal - you'll get an error like "error C2296: '<<' : illegal, left operand has type 'const char [20]'" - it won't give a useful value for the stringstream constructor. The problem is that the compiler's still trying to apply the bitwise shift operator, which only makes sense for numbers, as the overloads for << that we'd want to apply require a left-hand argument of type ostream&. C++ requires the value being evaluated on the right of = to be evaluated independently of the assignment that's eventually done with the resultant value, and at that point the type of the variable being constructed is not relevant to the way evaluation is attempted on the expression being assigned.

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

It's a bit of a chicken-and-egg problem here, because you kind of need to combine the right-hand values you want in the stringstream to call the stringstream's constructor, but for that you need... a stringstream. You can actually pull that off with a temporary stringstream:

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

不幸的是,需要强制转换,因为 operator<< 重载通过引用 ostream 基类来处理 stringstream s,并返回 ostream& ,因此您需要手动回退为 stringstream 类型,以便随后可以调用 std :: stringstream 移动构造函数...

The cast is unfortunately needed because the operator<< overloads handle stringstreams via references to their ostream base class, returning an ostream&, so you need to cast back to the stringstream type manually, so you can then invoke the std::stringstream move constructor...

然后是完整的单线构造...

The complete one-liner construction is then...

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

...但这太可怕了,无法考虑.

...but that's too hideous to contemplate.

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

Depending on your sensibilities, you may feel a macro helps or is worse...

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

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

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

FWIW, you could also use the macro to create strings...

std::string s(OSS("Number of people is " << numPeople).str()); 

(可以说)更好的实践

只需创建 stringstream -可以选择向构造函数提供单个 string -然后在第二条语句中使用 operator<< :

An (arguably) better practice

Just create the stringstream - optionally providing a single string to the constructor - then use operator<< in a second statement:

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

这更容易阅读.对于移动构造,经过优化后,可能没有性能上的原因选择两个语句.

This is much easier to read. With move construction, after optimisation there's likely no performance reasons for preferring two statements.

C ++ 11引入了 to_string() 重载,如果您有一个整数值或两个整数值与 string 相匹配或包含在 string 中,则很方便:

C++11 introduced to_string() overloads which are convenient if you have an integral value or two to concatentate with or into a string:

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

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

This may be inefficient though (check your compiler(s) optimisation abilities if you care): each std::to_string() is likely to dynamically allocate a buffer for an independent std::string instance, then the individual concatenations may involve extra copying of text, and the original dynamically-allocated buffers may need to be enlarged, then most of those temporary std::strings will take time to deallocate during destruction.

C ++ 03缺少移动构造函数,因此有必要使用 <临时成员上的code> std :: ostringstream :: str() 成员函数以获得 std :: string 的额外深层副本,利用该副本可以构造命名的 stringsteam ...

C++03 lacked move constructors, so it was necessary to use the std::ostringstream::str() member function on the temporary to get an extra deep-copy of the std::string with which to construct the named stringsteam...

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

使用此C ++ 03代码,可能会出现重复的动态内存分配和内容副本,因此按流进行构造是更好的选择.

With this C++03 code, there's a likelihood of duplicate dynamic memory allocations and a copy of content, so construction-followed-by-streaming was a better bet.

这篇关于如何初始化std :: stringstream?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆