原始数据类型在循环内分配了多少次?

How many times are primitive data types allocated inside loops?

这是一个例子:

while (i < 10)
    {
        int j = 1;
        string k = "hello.";
    }

j 是原始数据类型,k 是对象。根据Do built-in types have default constructors?,

So non-class types (including fundamental types, array types, reference types, pointer types, and enum types) do not have constructors.

并且根据Declaring Variables inside Loops, good practice or bad practice? (2 Parter),

the constructor and destructor must be executed at each iteration in the case of an object (such as std::string).

然而,variable declaration within the while loop C/C++ 说,

while(i--)
    {
      int i=100; // gets created every time the loop is entered
      i--;
      printf("%d..",i);
    } // the i in the loop keeps getting destroyed here

我了解到,当一个函数被调用时(例如 main() 被操作系统调用),所有局部变量都在函数开始时创建并在函数结束时销毁。上面的 while 循环引用是说原始数据类型 i 在 while 循环块中声明时被创建,并在每次迭代的 while 循环块结束时销毁。

这是真的吗? #1 是否为 while 循环的每次迭代分配了在 while 循环块中声明的原始数据类型? #2 我认为 while 循环中的这些声明应该在包含 while 循环块的函数的开头创建是错误的吗?

我正在寻找详细的解释,而不仅仅是是或否。

程序的行为必须就好像它在每次循环中都被重新分配(然后解除分配)。

程序表现出这种行为的机制完全取决于编译器。在许多情况下,根本不会为变量分配 space,或者它可能根本不存在! (例如第一个示例中的 j

如果 space 确实被分配了,我认为通常 space 在调用包含循环的函数时被保留。 (并且 space 不一定 独占 保留)

是的,当您在循环内声明一个变量时,程序的行为就好像在每次循环迭代中创建和销毁该变量一样。因此,如果变量具有 class 类型,则程序的行为 就好像 它的构造函数和析构函数每次都被调用。

然而,由于优化,无法观察到的行为可以被移除,所以第一个循环可以完全优化掉,第二个循环可以优化成类似

while(i--)
    printf("%d..", 99);

所以可能会出现没有创建实际变量的情况。

从逻辑上讲,是的,变量在循环的每次迭代的循环体开始时创建,并在结束时销毁。

在您的第一个示例中,std::string 的构造函数(实际上是 std::basic_string<char>,即 std::string 是什么)将在每次迭代时被调用,析构函数也是如此。类似地,正在创建 j 并将每次迭代设置为 1

在第二个示例中,出于同样的原因,i 将使用值 99 打印。

编译器在这方面确实有一些回旋余地。如果他们可以检测到重复创建和销毁没有影响,他们可以让变量保持活动状态,并在每次循环迭代时简单地重新初始化它。他们甚至可以完全消除变量(例如,只重复打印 99,而不创建变量)。但是,这样的事情不能依赖,程序无法测试它是否发生。