如何初始化std :: stringstream?

Dra*_*ir5 19 c++ stringstream

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

int numPeople = 10;
stringstream ss;
ss << "Number of people is " << numPeople;
Run Code Online (Sandbox Code Playgroud)

这很有效.但我试图通过以下方式做到:

int numPeople = 10;
stringstream ss << "Number of people is " << numPeople;
Run Code Online (Sandbox Code Playgroud)

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

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

Ton*_*roy 32

stringstream ss << "Number of people is " << numPeople;
Run Code Online (Sandbox Code Playgroud)

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

这类似于希望这可以工作:

int x + 3 + 9;
Run Code Online (Sandbox Code Playgroud)

问题

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

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

int x = 3 + 9;
Run Code Online (Sandbox Code Playgroud)

...它的工作原理是因为"3 + 9"可以先独立评估,以便给出一个合理的值来存储x. 编译器+ints的运算符的行为做了我们想要的:它产生int我们想要存储的结果x.但是,如果你尝试stringstream...

stringstream ss = "Number of people is " << numPeople;  // BROKEN
Run Code Online (Sandbox Code Playgroud)

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

一个办法

这里有一个鸡与蛋的问题,因为你需要将你想要的右手值组合起来stringstream调用它stringstream的构造函数,但为此你需要... a stringstream.你可以用一个临时的方法来解决这个问题stringstream:

static_cast<std::ostringstream&&>(std::ostringstream() << "Number of people is " << numPeople)
Run Code Online (Sandbox Code Playgroud)

不幸的是需要强制转换,因为operator<<重载stringstream通过引用它们的ostream基类来处理,返回一个ostream&,所以你需要stringstream手动转换回类型,这样你就可以调用std::stringstream移动构造函数了...

那么完整的单线结构就是......

std::stringstream ss(static_cast<std::ostringstream&&>(std::ostringstream() << "Number of people is " << numPeople));
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

std::stringstream ss(OSS("Number of people is " << numPeople));
Run Code Online (Sandbox Code Playgroud)

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

std::string s(OSS("Number of people is " << numPeople).str()); 
Run Code Online (Sandbox Code Playgroud)

(可以说是)更好的做法

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

std::stringstream ss;
ss << "Number of people is " << numPeople;
Run Code Online (Sandbox Code Playgroud)

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

替代

C++ 11引入了to_string()重载,如果你有一个或两个整数值来连接或者进入string:

std::string s = "Number of people is " + std::to_string(numPeople);
Run Code Online (Sandbox Code Playgroud)

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

在C++ 03中更糟糕

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

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

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