在c++中,没有变量名的构造函数调用的生存期/作用域是什么?

In C++, what is the lifetime/scope of a constructor call without a variable name?

本文关键字:生存期 函数调用 作用域 是什么 变量名 c++      更新时间:2023-10-16

在今天早上的一些编码过程中,我设法输入并编译了类似于下面的东西。

void a_function(void)
{
    A_Class(std::string);
    ... //Other code continues
}

(名称已被替换以保护所涉及的类的身份)

我想要的是一个命名实例A_Class an_instance(a_string);,我知道它将在函数结束前的作用域中。在这个函数中创建的A_Class的作用域和生存期是什么?


我希望我能在建设阶段做一些聪明的事情,让我的一生几乎是我想要的。在这种情况下,构造函数调用函数并执行printf,析构函数也执行类似的操作。没有调用new, delete, malloc或类似的任何东西。

从c++ 98开始,除非通过绑定到引用来延长其生命周期,否则临时变量将一直持续到完整表达式结束。

我记得,在ARM (Stroustrup和Ellis的注释参考手册)和c++中,规则是不同的。

一般来说,仅仅通过检查调试器中的示例或通过跟踪语句来确定标准的保证是不可能的,所以这个问题是有价值的。

只有名字有作用域,所以这个概念在这里是不相关的。

您正在创建一个临时对象。
与所有临时对象一样,它的生命周期一直持续到创建它的完整表达式的末尾,即在本例中直到";",除非它绑定到const引用变量。

表达式:

A_Class();

创建A_Class类的临时对象。临时变量在对包含它的完整表达式求值后被销毁——在这种情况下,临时变量在构造完成后立即被销毁。

为了回答我自己的问题,

的第二次尝试

更新后的测试代码现在是:

#include <iostream>
class Class_A 
{
public:
  Class_A(std::string a_string) 
    : saved_string(a_string)
  {
    std::cout << "Class_A Constructed:" << saved_string << std::endl;
  }
  ~Class_A() 
  {
    std::cout << "Class_A Deconstructed:" << saved_string << std::endl;
  }
  std::string saved_string;
};
class Class_B 
{
public:
  Class_B(std::string a_string) 
    : saved_string(a_string)
  {
    std::cout << "Class_B Constructed:" << saved_string << std::endl;
  }
  ~Class_B() 
  {
    std::cout << "Class_B Deconstructed:" << saved_string << std::endl;
  }
  std::string saved_string;
};

int main () 
{
  std::cout << "Welcome to the lifetime test." << std::endl;
  Class_A a_a("A");
  Class_B a_b("B"); //Now I have to have () here too
  std::cout << "Now for the interesting bit." << std::endl;
  Class_A("a"); //Have to have the ()
  Class_B("b");
  std::cout << "Fin." << std::endl;
  return 0;
}

当执行时产生:

$ ./a.out 
Welcome to the lifetime test.
Class_A Constructed:A
Class_B Constructed:B
Now for the interesting bit.
Class_A Constructed:a
Class_A Deconstructed:a
Class_B Constructed:b
Class_B Deconstructed:b
Fin.
Class_B Deconstructed:B
Class_A Deconstructed:A

所以我现在可以看到生命周期,我被迫在适当的地方使用()("string")。有点奇怪的是,a_a()在第一次尝试中是函数内部的函数声明,但' a_a_(" a ")在第二次尝试中是构造函数。我没有意识到允许在其他函数的定义中声明函数,但我想这在一些情况下是有意义的,当你可能在后台有一些奇怪的联系。

未命名的临时变量的生存期与它所在的表达式的生存期相同。直到;

第一次尝试

我读到:

class Class_A 
{
public:
  Class_A() 
  {
    std::cout << "Class_A Constructed" << std::endl;
  }
  ~Class_A() 
  {
    std::cout << "Class_A Deconstructed" << std::endl;
  }
};
class Class_B 
{
public:
  Class_B() 
  {
    std::cout << "Class_B Constructed" << std::endl;
  }
  ~Class_B() 
  {
    std::cout << "Class_B Deconstructed" << std::endl;
  }
};
int main () 
{
  std::cout << "Welcome to the lifetime test." << std::endl;
  Class_A a_a();
  Class_B a_b;
  std::cout << "Now for the interesting bit." << std::endl;
  Class_A(); //Have to have the ()
  Class_B();
  std::cout << "Fin." << std::endl;
  return 0;

生产:

$ g++ main.cpp
$ ./a.out 
Welcome to the lifetime test.
Class_B Constructed
Now for the interesting bit.
Class_A Constructed
Class_A Deconstructed
Class_B Constructed
Class_B Deconstructed
Fin.
Class_B Deconstructed

所以我只构造了1个Class_A。这有点令人困惑,因为我本以为a_aa_b具有相同的寿命。现在我做了什么。
(更新后,我确信)

它似乎表明对没有变量名的构造函数的调用只存在于它们所在的行/语句中(直到;)。当我考虑函子时,这是有道理的,正如@douglas-o-moen

所指出的那样