当前位置: 首页 > 知识库问答 >
问题:

为什么结构的析构函数是否运行取决于成员变量的类型?

庄嘉
2023-03-14

我对C++还很陌生,在研究构造函数和析构函数行为时,我发现了这个问题:

#include <iostream>
using namespace std;
struct Student
{
    string a;
    ~Student()
    {
        cout << "Destructor called" << endl;
    }
};
Student S;
void TesDes()
{
    cout << "Call TesDes" << endl;
    S = {"uet"};
}
int main(int argc, char *argv[])
{
    cout << "start" << endl;
    TesDes();
    cout << S.a << endl;
    return 0;
}

当我运行上面的代码时,输出是:

start
Call TesDes      
Destructor called
uet
Destructor called

但是,当我将字符串A;更改为int A;并将s={“uet”};更改为s={2};时,则输出为:

start
Call TesDes
2
Destructor called

有人能解释一下为什么这个改变会使析构函数少运行一次吗?

共有1个答案

董宜然
2023-03-14

你看到的是拷贝的剪辑。这是一种在某些情况下将绕过临时对象构造的优化。

在GCC中,可以通过传递以下编译器标志来禁用它(尽管通常不建议这样做):

-fno-elide-constructors

在您的例子中,我相信优化是由于结构变成了一个普通类型而触发的,因此它被视为POD(普通旧数据),内存被简单地修改而不构造一个对象。

显示-fno-elide-constructors效果的现场演示:https://godbolt.org/z/6eqe8ea69

 类似资料:
  • 主要内容:使用“键值对”初始化结构体,使用多个值的列表初始化结构体,初始化匿名结构体结构体在实例化时可以直接对成员变量进行初始化,初始化有两种形式分别是以字段“键值对”形式和多个值的列表形式,键值对形式的初始化适合选择性填充字段较多的结构体,多个值的列表形式适合填充字段较少的结构体。 使用“键值对”初始化结构体 结构体可以使用“键值对”(Key value pair)初始化字段,每个“键”(Key)对应结构体中的一个字段,键的“值”(Value)对应字段需要初始化的值。 键值对的

  • 主要内容:在类体中和类体外定义成员函数的区别类可以看做是一种数据类型,它类似于普通的数据类型,但是又有别于普通的数据类型。类这种数据类型是一个包含成员变量和成员函数的集合。 类的成员变量和普通变量一样,也有数据类型和名称,占用固定长度的内存。但是,在定义类的时候不能对成员变量赋值,因为类只是一种数据类型或者说是一种模板,本身不占用内存空间,而变量的值则需要内存来存储。 类的成员函数也和普通函数一样,都有返回值和参数列表,它与一般函数的区别是

  • 如果我有一个封装两个成员的结构,并基于另一个成员更新其中一个,那么只要我这样做就可以了: 也就是说,当我直接提到self时。b 。但当我将do\u stuff()更改为以下内容时: 编译器抱怨:<代码>无法将`*self`借用为不可变,因为` self `。a `也被借用为可变的。 如果我需要执行比返回成员更复杂的操作来获取a.do\u something()的参数,该怎么办?我必须创建一个按值返

  • 我读到虚拟析构函数必须在具有虚拟方法的类中声明。我只是不明白为什么必须宣布它们是虚拟的。我从下面的例子中知道为什么我们需要虚拟析构函数。我只是想知道为什么编译器不为我们管理虚拟析构函数。关于虚拟析构函数的工作,有什么我需要知道的吗?以下示例显示,如果析构函数未声明为虚拟,则派生类的析构函数不会被调用,这是为什么?

  • 为了节省内存(是的,它很重要),如果为false,我想省略浮动。由于中还有很多其他内容,因此最好的方法如下所示: 不过,据我所知,在C++中没有零大小的类型。唯一的例外似乎是“灵活数组成员”,所以我也许可以做一些类似的事情: 只不过它们只在C99中得到支持,而不是在C++中得到支持。 标准的解决方案似乎是使用继承,因为基类可以是零大小的,但是我的结构也可以由程序集访问,为了使程序集更简单,如果在结

  • 我试图理解在将值存储到结构或联合的成员中时,类型双关是如何工作的。 标准N1570指定 当值存储在结构或联合类型的对象(包括成员对象)中时,与任何填充字节相对应的对象表示的字节采用未指定的值。 所以我把它解释为如果我们有一个对象要存储到一个成员中,这样对象的大小等于,与填充相关的字节将具有未指定的值(即使我们定义了原始对象中的字节)。这是一个例子: 在我的机器。 打印的行为是否为这样的程序定义得很