nsivakr
nsivakr

Reputation: 1595

Why the destructors are called twice for this functor?

When I run the following program, the destructor is called twice and I'm trying to understand why?

#include <iostream>
#include <vector>
#include <algorithm>

class sample
{
    public:
        sample() { std::cout << "Constructor " << std::endl; }

        ~sample() { std::cout << "Destructor" << std::endl; }

        void operator()(int i)
        {
            std::cout << i << " , "  << std::endl;
        }
};

int main()
{

    std::vector<int> iNumbers;

    for ( int i = 0 ; i < 5 ; ++i)
        iNumbers.push_back(i);

    std::for_each(iNumbers.begin() , iNumbers.end() , sample() );
}

The output is as folllows

Constructor
0 ,
1 ,
2 ,
3 ,
4 ,
Destructor
Destructor

Upvotes: 2

Views: 646

Answers (4)

David Schwartz
David Schwartz

Reputation: 182819

Classic rule of three violation. Try this:

#include <iostream>
#include <vector>
#include <algorithm>

class sample
{
    public:
        sample() { std::cout << "Constructor " << std::endl; }

        sample(const sample&) { std::cout << "Constructor (copy)" << std::endl; }

        ~sample() { std::cout << "Destructor" << std::endl; }

        sample& operator=(const sample&) { return *this; }

        void operator()(int i)
        {
                std::cout << i << " , "  << std::endl;
        }
};

int main()
{
    std::vector<int> iNumbers;

    for ( int i = 0 ; i < 5 ; ++i)
            iNumbers.push_back(i);

    std::for_each(iNumbers.begin() , iNumbers.end() , sample() );
}

Output is:

Constructor
0 ,
1 ,
2 ,
3 ,
4 ,
Constructor (copy)
Destructor
Destructor

Upvotes: 5

Alex Chamberlain
Alex Chamberlain

Reputation: 4207

If you wrote a copy constructor, you would see that the functor is copied into the algorithm. Both copies are then destructed. There is a potential for the functor to be returned and there would be 3 copies, so one of the copies is being elided.

Upvotes: 1

Joseph Mansfield
Joseph Mansfield

Reputation: 110698

std::for_each will take the function object by value, causing it to be copied. So one destructor is called for the temporary object created by sample() and the other for the copy.

Upvotes: 2

Andy Prowl
Andy Prowl

Reputation: 126502

The reason is that std::for_each takes its argument by value, and this results in a copy of the argument you provide being made.

Therefore, the destruction of the temporary you create by doing sample() will be responsible for one of those two destruction messages (the last one, since the temporary is destructed after the evaluation of the full expression that creates it).

The first destruction message, on the other hand, comes from the destruction of the copy that std::for_each is working on.

Upvotes: 3

Related Questions