当您多次声明相同的对象/变量时会发生什么(新手)

时间:2012-01-17 02:17:48

标签: c++

这样的事情是做什么的?

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数组一起使用会更聪明吗?

2 个答案:

答案 0 :(得分:6)

每次调用该函数时,都会在堆栈上推送一个新的本地std::stringstream ss实例。在函数结束时,该实例被销毁并从堆栈中弹出。

在任何时候,函数update_text的范围在其范围内都有多个变量,标识符为ss。因此,在update_text的范围内,只有一个ss标识符。

字符数组没有区别。每次调用该函数时,char数组(如果静态分配)将被压入堆栈并在结尾处弹出。如果使用动态内存并动态分配字符数组,则每次调用函数时仍会执行newdelete语句,并且仍会推送和弹出指向此字符数组的指针堆栈。 std::stringstream已在内部为您处理newdelete

多次声明一个对象看起来像这样:

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`)。