首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >向量与push_back()行为

向量与push_back()行为
EN

Stack Overflow用户
提问于 2015-10-09 10:09:37
回答 3查看 275关注 0票数 3

我正在学习理解类构造函数和析构函数。我编写了一个小型控制台代码,将一个类实例添加到向量中。这一切都很好,但我不明白的是,在向量中添加一个对象会触发两次析构函数。这一切为什么要发生?

如果我不添加任何对象,向量本身就不会触发构造函数或析构函数,那么为什么会发生两次呢?

有人能解释一下为什么会发生这种事吗?

代码语言:javascript
复制
#include <cstdio>
#include <vector>
class Test
{
    private:
        int value;

    public:
        Test()
        {
            printf("\nClass constructor triggered.");
        };
        ~Test()
        {
            printf("\nClass desctructor triggered.");
        }
};

int main()
{
    std::vector<Test> container;

    container.push_back( Test() );
    return 0;
}

更新:我向类添加了更多信息,以便获得更具体的输出,但是现在我注意到,随着向量的每一次添加,移动构造和析构函数调用都会增加。这些调用的数量是否与向量内的对象数量或正在发生的情况有关?我在泄密吗?抱歉如果问题太蠢了。以下是添加的代码:

代码语言:javascript
复制
#include <cstdio>
#include <vector>

class Test
{
    private:
        int value;

    public:
        // Constructor
        Test(int v=0)
        {
            value = v;
            printf("\n\n%i", value);
            printf("\nClass constructor triggered.");
        };

        // Copy-move constructor
        Test(Test&&)
        {
            printf("\nClass move-constructor triggered.");
        };

        // Destructor
        ~Test() 
        {
            value = 0;
            printf("\nClass desctructor triggered.");
        }
};

int main()
{
    std::vector<Test> container;

    container.push_back( Test(1) );
    container.push_back( Test(2) );
    container.push_back( Test(3) );
    container.push_back( Test(4) );

    printf("\n\nPushback complete!");
    return 0;
}
EN

回答 3

Stack Overflow用户

发布于 2015-10-09 10:12:50

向量包含通过push_back()添加到它的对象的副本。第一次析构函数调用是由于在包含对push_back()的调用的完整表达式末尾创建的临时销毁。当向量本身被销毁时,第二析构函数是由正在被销毁的向量内的副本引起的。

您可以通过在main()中添加诊断信息来说服自己

代码语言:javascript
复制
int main()
{
    std::vector<Test> container;

    container.push_back( Test() );

    printf("\nThis is before the vector is destroyed...");

    return 0;
}

您可以在这个http://coliru.stacked-crooked.com/a/19d3e574e30be028中观察输出。

您的向量包含的副本是通过为类调用自动生成的移动构造函数(而不是使用默认构造)创建的,这就是为什么您没有看到相应的构造诊断。

如果您定义了自己的move构造函数(或复制构造函数,如下所示)来发出诊断,则输出将更接近您预期的结果:

代码语言:javascript
复制
    Test(Test const&)
    {
        printf("\nCopy construction triggered.");
    };

再说一遍,http://coliru.stacked-crooked.com/a/5a11d66e9434cc84

票数 6
EN

Stack Overflow用户

发布于 2015-10-09 10:13:07

为了简单起见,让我们假设您正在使用C++03,而且移动语义还不可用。

添加复制构造函数,以确保它也被触发。

代码语言:javascript
复制
Test(const Test&)
{
    printf("\nClass copy constructor triggered.");
};

输出

代码语言:javascript
复制
Class constructor triggered.
Class copy constructor triggered.
Class destructor triggered.
Class destructor triggered.

因此,有两个对象被构造/破坏。

粗略地说,您的代码等于

代码语言:javascript
复制
int main()
{
    std::vector<Test> container;

    Test test;                    // first object created
    container.push_back(test);    // second object created by copying
    return 0;
}
票数 2
EN

Stack Overflow用户

发布于 2015-10-09 10:13:19

push_back()不触发任何析构函数(在本例中)。

Test的析构函数的两个调用是:

1-因为您将一个临时对象传递给push_back(),所以当push_back()完成时,该对象就会被销毁。

2-当程序结束时,vector就会被破坏,所以它就是内容

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33035512

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档