重用字符串流而不重新分配
reusing a stringstream without re-allocation
我正在尝试弄清楚如何重用字符串流对象,而无需每次在流中放入某些内容时都重新分配底层字符串。我找到了这个答案,导致我这样做:
int main() {
stringstream ss;
int x;
ss << "423";
ss >> x; // x is now 423
ss.clear();
ss.seekg(0);
ss.seekp(0);
ss << "1";
ss >> x; // x is now 123. Instead I want x to be 1.
std::cout << x << std::endl;
}
不幸的是,这不起作用,因为第一次传递的字符串内容仍然存在(第一次传递后字符串被"423"
,第二次传递后它们被"123"
(。但是,如果我在第二个放置之后添加一个空格,事情似乎可以正常工作,如下所示:
int main() {
stringstream ss;
int x;
ss << "423";
ss >> x; // x is now 423
ss.clear();
ss.seekg(0);
ss.seekp(0);
ss << "1";
ss << " "; // add a space right after the desired value
ss >> x; // x is now 1
std::cout << x << std::endl;
}
第二次传递后,字符串"1 3"
。我对I/O库不是很熟悉,我想知道上述方法是否安全,或者它是否恰好在这个微不足道的例子中起作用,或者是否有更好的解决方案。实时代码在这里。谢谢!
我用这段代码使用 clang 做了一些调查和实验:
测试代码
class LogHelper {
public:
~LogHelper() {
std::cout << out.str() << 'n';
}
std::ostream &stream() {
return out;
}
private:
std::ostringstream out;
};
#define LOG() LogHelper().stream() << __FUNCTION__ << '(' << __LINE__ << ")"
#define VAR(x) ", " #x "[" << x << ']'
class MyAllocator : public std::allocator<char> {
public:
using base = allocator<value_type>;
using base::allocator;
value_type* allocate( std::size_t n, const void * hint) {
LOG() << VAR(n);
return base::allocate(n, hint);
}
value_type* allocate( std::size_t n ) {
LOG() << VAR(n);
return base::allocate(n);
}
void deallocate( value_type* p, std::size_t n ) {
LOG() << VAR(n);
base::deallocate(p, n);
}
};
using MySStream = std::basic_stringstream<char, std::char_traits<char>, MyAllocator>;
using MyString = std::basic_string<char, std::char_traits<char>, MyAllocator>;
int main() {
MySStream ss; // (MyString(255, ' '));
ss.clear();
int x;
ss << "423";
ss << " 423";
LOG();
ss << " 423jlfskdfjl jfsd sdfdsfkdf dsfg dsfg dfg dfg dsfg df gdf gdfg dsfg dsfgdsfgds";
LOG();
ss >> x;
ss.clear();
ss.str({});
ss.seekg(0);
ss.seekp(0);
ss << "1";
ss >> x;
std::cout << x << std::endl;
LOG();
return 0;
}
- 您的示例与渴望分配 CLANG、Visual Studio、GCC 7.3 忽略自定义分配器,GCC 8.x 不编译
main(55)
allocate(34), n[48]
allocate(34), n[96]
deallocate(39), n[48]
main(57)
1
main(70)
deallocate(39), n[96]
- 在流叮当声中预设长字符串,视觉工作室
allocate(34), n[256]
allocate(34), n[256]
deallocate(39), n[256]
main(55)
main(57)
1
main(70)
deallocate(39), n[256]
我有几个发现
- Clang和Visual 的行为同样卑鄙,GCC对此代码有一些Stang问题。
std::basic_stringstream
字符串缓冲区始终增长,永不收缩std::basic_stringstream
糟透了。您不能保留字符串大小或缓冲区大小,例如大小写std::string
。自定义分配器只能按类型传递,不能按对象提供分配器。- 要减少分配,您必须在乞求处设置大字符串,然后直到您不成功,其容量重新分配将不会发生(第二个示例(。
- 提供自定义分配器没有多大帮助,并且在获取结果字符串时会添加样板代码。在我的示例中,它主要用于记录分配和解除分配。
ss.str({});
不会导致分配。这里的小字符串优化有助于
结论:
- 您可以按照您链接SO答案中的建议安全地执行
ss.str({});
,并且不会导致分配。在这里,小字符串优化有所帮助,并且 - 自定义分配器不是很有帮助
- 在乞讨时设置大假绳是相当有效的邪恶黑客
- 寻找替代方案应该是更好的方法(也许是提升 - 我没有测试它(
- 第
1
点和您的问题表明您没有进行任何测量,您的问题基于个人假设。
相关文章:
- 新分配指向函数的指针是否合法?
- 变体 - 分配新值时是否清理旧值?
- 分配新的零大小数组可以具有有效价值吗?
- 当我尝试为结构分配新指针时出现堆栈溢出错误
- 在函数返回中返回对新分配的shared_ptr的尊重合法吗
- 如何删除新分配的字符,这也是函数返回值?
- C ++中新分配的int的内存大小,有没有不同更好的方法来查看它?
- OpenSSL:当输出ptr为空时,BIGNUM的bin2bn不会分配新的BIGNUM
- 每次我分配新的位置时,都会隐式地称为destuructor
- 为什么这个指针到指针的二维数组像这样分配新的 int
- 如何创建对象变量,以便每次分配新的指针
- C 新操作员分配新内存
- 编译器忽略运算符新分配
- 方法向量的新/分配的复杂性::p ush_back
- 有没有一种方法可以全局填充新分配/删除分配
- 调用时为 std::function 分配新值
- 为什么我的新分配指针会自动在程序退出上删除
- 如果我尚未为指针分配新值,是否需要删除指针?
- OpenCV:为矩阵元素分配新值
- 在避免新分配的同时,const变量的复杂初始化