这样的事情是做什么的?
static int i;
// wrapped in a big loop
void update_text()
{
std::stringstream ss; // this gets called again and again
++i;
ss << i;
text = new_text(ss.str()); // text and new_text are defined elsewhere
show_text(text); // so is this
}
是否在堆栈中使用新地址和所有内容创建新的ss实例?将sprintf与char数组一起使用会更聪明吗?
答案 0 :(得分:6)
每次调用该函数时,都会在堆栈上推送一个新的本地std::stringstream ss
实例。在函数结束时,该实例被销毁并从堆栈中弹出。
在任何时候,函数update_text
的范围在其范围内都有多个变量,标识符为ss
。因此,在update_text
的范围内,只有一个ss
标识符。
字符数组没有区别。每次调用该函数时,char数组(如果静态分配)将被压入堆栈并在结尾处弹出。如果使用动态内存并动态分配字符数组,则每次调用函数时仍会执行new
和delete
语句,并且仍会推送和弹出指向此字符数组的指针堆栈。 std::stringstream
已在内部为您处理new
和delete
。
多次声明一个对象看起来像这样:
void Function()
{
int x;
int x;
}
这会导致编译错误。
请注意,这是有效的:
void Function()
{
int x;
if(true)
{
int x;
}
}
因为这两个变量的范围不同。第二个x
仅存在于if
语句中。因此,编译器可以推断在该声明之后和该范围内对x
的任何引用都是指第二个x
。请注意,类型无关紧要,重要的是标识符或“名称”。
答案 1 :(得分:0)
小点:你的问题不是关于再次声明一个对象,而是遇到一个对象初始化多一次的位置。
所以回答你的真实问题:是的,每次调用函数时它都会创建ss
的新实例(尽管如果从循环中调用它,那么地址实际上是相同的,但实际上是应该对程序员无关紧要)。
对于你的第二个问题:将sprintf
与char数组一起使用会更聪明吗?好吧,如果你是c ++的新手,你应该从中得到的答案是否定的,因为sprintf
使用streams
更加危险(缺乏类型安全,溢出风险)。实际的答案取决于它。如果您知道自己在做什么,请使用sprintf
,使用stringstreams
获得的效果不足以达到您的目的(这种情况很少发生)。此外请注意,您可以重复使用stringstreams
,这样可以减少每次创建新内容的开销(这对于流式传输单个int
很重要),您还可以查看Boost.Lexical_Cast
此类型的铸件。根据他们的the performance section of there documentation,它应该与sprintf
一样快,例如将int
转换为string
(我自己没有测试过,所以没有保证),而不会暴露缺乏sprintf
的类型安全(以及缓冲区溢出风险) C ++ 11也有std::to_string
,它可以在不放弃安全的情况下进行转换(但它的灵活性远低于boost :: lexical_cast`)。