代码之家  ›  专栏  ›  技术社区  ›  pandoragami

对象的C++向量和对析构函数的过度调用?

  •  0
  • pandoragami  · 技术社区  · 13 年前

    我想知道的是,代码是否多次调用析构函数,以及以这种方式编码是否正确。创建的对象在加载到向量中之前似乎超出了范围,但对象并没有死亡,而是停留在向量中,并在程序完成后再次破坏。输出如下:

    object::constructor:
    before push_back
    object::destructor:
    object::constructor:
    before push_back
    object::destructor:
    object::destructor:
    object::call(): begin
    0
    object::call(): end
    object::call(): begin
    1
    object::call(): end
    object::destructor:
    object::destructor:
    
    Process returned 0 (0x0)   execution time : 0.313 s
    Press any key to continue.
    

    这是主.cpp

    #include <vector>
    #include <iostream>
    #include "object.h"
    
    int main()
    {
        int max = 2;
        std::vector <object> OBJECTS;
    
        for(int index = 0; index < max; index++)
        {
                object OBJECT(index);
                std::cout<<"before push_back"<<std::endl;
                OBJECTS.push_back(OBJECT);
        }
    
        for(int index = 0; index < max; index++)
            OBJECTS[index].call();
    
        return 0;
    }
    

    这就是物体

    #ifndef OBJECT_H
    #define OBJECT_H
    
    #include <iostream>
    
    class object
    {
            private:
    
                int value;
    
            public:
    
            object(){}
            object(int value)
            {
                std::cout<<"object::constructor: "<<std::endl;
                this->value = value;
            }
            ~object()
            {
                std::cout<<"object::destructor: "<<std::endl;
            }
            void call()
            {
                std::cout<<"object::call(): begin"<<std::endl;
                std::cout<<value<<std::endl;
                std::cout<<"object::call(): end"<<std::endl;
            }
    };
    #endif
    

    这是下面Chowlett回答中的代码,以防网站崩溃。

    #include <iostream>
    #include <vector>
    
    class object
    {
            private:
    
                int value;
    
            public:
    
            object(){}
            object(int value)
            {
                std::cout<<"object::constructor: "<< value << std::endl;
                this->value = value;
            }
            object( const object& o )
            {
               std::cout<<"object::copy-constructor: " << o.value << std::endl;
               this->value = o.value + 10;
            }
            ~object()
            {
                std::cout<<"object::destructor: "<< value << std::endl;
            }
            void call()
            {
                std::cout<<"object::call(): begin"<<std::endl;
                std::cout<<value<<std::endl;
                std::cout<<"object::call(): end"<<std::endl;
            }
    };
    
    int main()
    {
        int max = 3;
        std::vector <object> OBJECTS;
    
        for(int index = 0; index < max; index++)
        {
                object OBJECT(index);
    
                std::cout<<"before push_back: capacity="<< OBJECTS.capacity() << std::endl;            
                OBJECTS.push_back(OBJECT);
                std::cout<<"after push_back: capacity="<< OBJECTS.capacity() << std::endl;
        }
    
        for(int index = 0; index < max; index++)
            OBJECTS[index].call();
    
        return 0;
    }
    
    2 回复  |  直到 13 年前
        1
  •  3
  •   Daniel Frey    13 年前

    编译器为您生成了一个副本ctor。添加一个带有一些调试输出的代码,您就可以了解您的代码在做什么:

    object( const object& o )
    {
       std::cout<<"object::copy-constructor: "<<std::endl;
       this->value = o.value;
    }
    
        2
  •  2
  •   Chowlett    13 年前

    现在的情况是 vector 正在重新分配以腾出空间。

    OBJECTS 以开头 capacity 等于零。循环构造 OBJECT = object(0) ,然后copy构造该对象的副本以传递给 push_back . push _back 注意到空间不足(1>0!),因此重新分配 矢量 容量为1并放入副本。然后销毁 OBJECT .

    下次通过循环时, OBJECT = object(1) 构造,然后为 push_back 。又没有足够的空间了,所以 物体 被重新分配以具有更大的容量- 并且已经在其中的对象(0)被复制构造到重新分配的空间中,并且原始对象被销毁 。然后将复制的对象放入 对象 再次被破坏。

    This 代码的变化应该能清楚地表明发生了什么。我已经让代码编写了 矢量 每次之前和之后的容量 push_back ; 我添加了一个日志复制构造函数。我还让复制构建器将10添加到 value 每次调用时,您都可以看到每个人 object 被复制。

    推荐文章