如何初始化 std::stringstream
How to initialize a std::stringstream?
我需要用整数连接一个字符串。为此,我通过以下方式使用stringstream
:
int numPeople = 10;
stringstream ss;
ss << "Number of people is " << numPeople;
这奏效了。但我试图以以下方式做到这一点:
int numPeople = 10;
stringstream ss << "Number of people is " << numPeople;
我收到以下错误:">'<<'令牌之前的预期初始值设定项">
为什么我会收到此错误?为什么我不能在声明stringstream
值的同时分配它?
stringstream ss << "Number of people is " << numPeople;
为什么我不能在声明
stringstream
值的同时分配它?
这类似于希望这会起作用...
int x + 3 + 9;
。但这并不能解析为变量定义,更不用说定义和赋值了。
定义和初始化对象的合法方式
使用非默认值定义和初始化变量的唯一方法是(在语法意义上 - 这不是代码):
type identifier(...args...);
type identifier{...args...};
type identifier = ...expression...;
最后一个符号等效于第一个符号 - 即type identifier(arg)
arg 传递...expression...
的地方。
尝试对 int 和字符串流使用法律表示法
对于int
,您可以轻松更正代码:
int x = 3 + 9;
。它之所以有效,是因为可以首先独立评估"3 + 9",以给出一个合理的值以存储在x
中。编译器在int
上对运算符+
的行为做了我们想要的:它产生了我们想要存储在x
中的int
结果。 您可以将以上视为:
// evaluate the expression to assign first...
((int)3 + (int)9); // notate the implicit types
(int)12; // evaluate expression => value to assign
int x = (int)12; // then think about doing the assignment
int x((int)12); // construct a valid value
它有效! 但是,如果您尝试stringstream
stringstream ss = "Number of people is " << numPeople; // BROKEN
"Number of people is " << numPeople; // bitshift?!
。它不起作用,因为"Number of people is " << numPeople
需要先进行评估,但这是非法的 - 你会收到如下错误:
error C2296: '<<' : illegal, left operand has type 'const char [20]'
问题是编译器仍在尝试应用按位移位操作,这只对数字有意义,因为我们要使用的<<
重载要求任何"X <<Y"代码的左侧部分"X"是 - 或隐式转换为 -ostream&
。 无法转换字符串文本。 此时,编译器不会注意到表达式结果将传递到的stringstream
。
字符串流解决方案
这是一个先有鸡还是先有蛋的问题,因为您需要在stringstream
中组合您想要的右侧值来调用stringstream
的构造函数,但为此您需要......stringstream
. 您实际上可以通过临时stringstream
来完成它:
static_cast<std::ostringstream&&>(std::ostringstream{} << "Number of people is " << numPeople)
不幸的是,需要强制转换,因为operator<<
重载通过引用其ostream
基类来处理stringstream
,返回一个ostream&
,因此您需要手动转换回stringstream
类型,以便您可以调用std::stringstream
move 构造函数...
然后,完整的单线结构是...
std::ostringstream ss(static_cast<std::ostringstream&&>(std::ostringstream{} << "Number of people is " << numPeople));
...or...
auto&& ss = static_cast<std::ostringstream&&>(std::ostringstream{} << "Number of people is " << numPeople);
。但这太可怕了,无法想象。
使用宏使解决方案(可以说)不那么可怕
是的,你没看错。 根据您的感受,您可能会觉得宏有帮助或更糟......
#define OSS(VALUES)
static_cast<std::ostringstream&&>(std::ostringstream{} << VALUES)
auto&& ss = OSS("Number of people is " << numPeople);
FWIW,您还可以使用宏来创建字符串...
auto&& s = OSS("Number of people is " << numPeople).str();
。或创建专用的宏...
#define STR(VALUES)
static_cast<std::ostringstream&&>(std::ostringstream{} << VALUES).str()
auto&& s = STR("Number of people is " << numPeople);
(可以说)更好的做法 - 单独的构造和初始化
只需创建stringstream
- 可以选择向构造函数提供单个string
- 然后在第二个语句中使用operator<<
:
std::stringstream ss;
ss << "Number of people is " << numPeople;
这更容易阅读,并且不需要奇怪的宏。
另一种选择
C++11 引入了to_string()
重载,如果您有一两个整数值来连接或放入string
,则这些重载很方便:
auto&& s = "Number of people is " + std::to_string(numPeople);
不过,这可能效率低下(如果您关心,请检查您的编译器优化能力):每个std::to_string()
都可能为独立的std::string
实例动态分配缓冲区,然后单个串联可能涉及额外的文本复制,并且原始动态分配的缓冲区可能需要放大,然后大多数临时std::string
在销毁过程中需要时间来释放。
讨论
理想情况下,std::stringstream
会有一个构造函数接受任意数量的构造函数参数,这些参数(A, B, C...)
格式化为stringstream
,就像通过后续<< A << B << C...
一样。 已经有带有参数的构造函数(例如(std::ios_base::openmode, const Allocator&)
),因此我们需要一个占位符来区分此类参数与我们尝试格式化为流的值,或者更奇怪的解决方法,例如要求将要格式化的值作为初始化器列表传入流。
尽管如此,使用带有,
而不是<<
的字符串看起来和感觉都非常奇怪:
std::stringstream ss{"n:", std::setw(4), std::hex, 'n'};
然后,如果在代码维护期间发现需要在构造后将流值移动到某个点,则需要更改分隔符。 将其分成两行开始 - 施工然后流式传输 - 简化了维护。
03 C++年的情况更糟
C++03 缺少移动构造函数,因此有必要在临时上使用std::ostringstream::str()
成员函数来获取用于构造命名stringsteam
的std::string
的额外深度副本......
stringstream ss(static_cast<std::ostringstream&>(std::ostringstream() << "Number of people is " << numPeople).str());
使用此 C++03 代码,可能会重复的动态内存分配(除非字符串足够短以适合字符串对象,这是一种通常提供的std::string
技术,称为"短字符串优化"或 SSO)。 还有一个文本内容的深层副本。 先施工后流是一种更好的方法。
必须先初始化 stringbuf,然后才能向其添加值。 字符串流是一个对象。
通过做:
std::stringstream ss;
实质上是允许应用程序分配空间来处理要添加的值。
- 当我们进行一些操作时,应该使用什么'std::string'或'std::stringstream'?
- std::stringstream 返回字符 *
- std::stringstream::flush() 应该做什么吗?
- 静态 std::stringstream 的叮当整警告
- 为什么"std::stringstream::stringstream(std::string&&)"不存在?
- 为什么 {fmt} 比 std::stringstream 慢?
- C++命令末尾的 std::stringstream 空格
- 返回 std::stringstream - 编译失败
- C++ std::stringstream 运算符<< vs (构造函数)
- 流从STD :: Stringstream带有空间的流
- 用std :: stringstream inline代替字符
- 为什么我无法从 std::stringstream 二进制流中获得全精度(双精度、浮点数)
- C STD :: Stringstream操作优化
- 为什么GCC不允许我创建"内联静态std::stringstream"?
- What value should `std::stringstream::fail()` return after r
- 使用Boost Karma替换STD :: stringstream double到STD :: String Conv
- 从 std::stringstream 读取uint8_t为数字类型
- 重置std :: stringstream格式标志
- 如何将“char *”深度复制到std::stringstream
- C++ std::stringstream >> std::string 仅存储第一个条目?