Destructor is called when I push_back to the vector

前端 未结 4 549
青春惊慌失措
青春惊慌失措 2020-12-19 18:38

I have this class definition:

class FlashStream
{
public:
    explicit FlashStream(const char * url, vector * headers, vector * dat         


        
相关标签:
4条回答
  • 2020-12-19 18:47

    Destructor at push_back could be called in two cases.

    First case, as was noted, occurs when you push temporary object to vector. This is not the best idea, since constructor, copy constructor and destructor will be called. You may store pointers to object in your vector to avoid redundant calls.

    C++ 11 comes with new features that might help you.

    To avoid unnecessary copying use std::vector::emplace_back(Args&&... args)

    It constructs object in-place in vector instead of copying.

    Also you may use move version of push_back(value_type&& val). Just define move constructor in your class, and move version of push_back will work automatically for temporary objects.

    The second case when destructor is called is reaching capacity of the vector. Vector has two major values: size and capacity. Size is a number of elements currently held in vector. Capacity is size of internal vector storage measured in units of element type. So, when you push back element you are increasing size of vector. If size of storage is not enough to push new element, vector performs reallocation to increase its capacity. After reallocation vector re-constructs its object using copy constructor and deletes old objects using destructor. So, at psuh_back vector could invoke destructor of the object multiple times.

    To decrease cost of vector re-size at puhs_back, always use std::vector::reserve method to preallocate storage for your objects.

    std::vector<int> vec;
    vec.reserve(20);
    for(int i = 0; i<20; ++i)
        vec.push_back(i)
    

    Also you may decrease cost of object copying by defining move constructor.

    class C
    {
    public:
        C(int c)
            : m_c(c)
        {
            std::cout << "C(int c)" << std::endl;
        }
        C(C&& c)
            : m_c(c.m_c)
        {
            std::cout << "C(C&& c)" << std::endl;
        }
        C(const C& c)
            : m_c(c.m_c)
        {
            std::cout << "C(const C& c)" << std::endl;
        }
        ~C()
        {
            std::cout << "~C()" << std::endl;
        }
    private:
        int m_c;
    };
    
    int main()
    {
        std::vector<C> vc;
        for (int i = 0; i < 100; ++i)
            vc.push_back(C(i));
        return 0;
    }
    

    If you compile and run it you will see that "C(const C& c)" was not called at all. Since move version of constructor is defined, push_back and reallocate will move your object instead of copying.

    0 讨论(0)
  • 2020-12-19 18:53

    Putting copies of objects in vector/map etc. are bad idea. The destructor called when the temporary objects get destroyed. The destructor for the objects will be again called whenever the Vector/Map resizes or rearranges.

    To avoid those you should store pointer to those objects. You may like to use shared_ptrs here.

    0 讨论(0)
  • 2020-12-19 18:57

    This statement:

    _streams.push_back(FlashStream(url, headers, data, _npp.ndata, notifyData, lastModified));
    

    is equivalent to:

    {
        FlashStream temp(url, headers, data, _npp.ndata, notifyData, lastModified);
        _streams.push_back(temp);
        // temp gets destroyed here
    }
    

    so, you create a temporary FlashStream object that is copied into the vector, then destructed afterwards. You can avoid this by using emplace_back() in C++11:

    _streams.emplace_back(url, headers, data, _npp.ndata, notifyData, lastModified);
    
    0 讨论(0)
  • 2020-12-19 19:03

    You're creating a temporary object when you push back.
    He's the one which its desctructor is called.

    0 讨论(0)
提交回复
热议问题