Почему создается только один объект, а несколько объектов уничтожаются при использовании функтора? - PullRequest
2 голосов
/ 18 августа 2010

Следующий пример, бьет меня.До сих пор я думал, что когда используется функтор, объект создается один раз, а один и тот же объект используется несколько раз, когда используется с алгоритмом for_each, и это кажется правильным.

Однако, несмотря на то, что построен только один объект, уничтожено несколько объектов.Теперь, это бьет меня.

class print
{
public:
    void operator()(int i)
    {
        std::cout << i << std::endl;
    }

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

int main()
{

    std::vector<int> v;

    v.push_back(10);
    v.push_back(20);
    v.push_back(30);

    std::cout << "After assigning values " << std::endl;
    for_each(v.begin() , v.end() , print());
    std::cout << "After printing values " << std::endl;
}

Вывод выглядит следующим образом

After assigning Values
Constructor
10
20
30
Destructor
Destructor
Destructor
After printing values.

Как это возможно?

Ответы [ 4 ]

4 голосов
/ 18 августа 2010

Не забудьте о конструкторе копирования ( Правило трех * может помочь вам запомнить это):

class print
{
public:
    void operator()(int i)
    {
        std::cout << i << std::endl;
    }

    print()
    {
        std::cout << "Constructor " << std::endl;
    }

    print(const print& other) {
        std::cout << "Copy Constructor " << std::endl;
    }

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

int main()
{

    std::vector<int> v;

    v.push_back(10);
    v.push_back(20);
    v.push_back(30);

    std::cout << "After assigning values " << std::endl;
    for_each(v.begin() , v.end() , print());
    std::cout << "After printing values " << std::endl;
}

Вывод:

After assigning values 
Constructor 
Copy Constructor 
10
20
30
Copy Constructor 
Destructor
Destructor
Destructor
After printing values
1 голос
/ 18 августа 2010

Вот как у меня for_each в моей системе:

template<class _InIt,
    class _Fn1> inline
    _Fn1 _For_each(_InIt _First, _InIt _Last, _Fn1 _Func)  
    {   // perform function for each element
    for (; _First != _Last; ++_First)
        _Func(*_First);
    return (_Func);                 // a copy could be created here (C3)
    }

    template<class _InIt,
        class _Fn1> inline
        _Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
        {   // perform function for each element
        _DEBUG_RANGE(_First, _Last);
        _DEBUG_POINTER(_Func);
        return (_For_each(_Unchecked(_First), _Unchecked(_Last), _Func)); // a copy created here (C2)
        }

Итак, по сути, вот как может выглядеть

for_each(v.begin() , v.end() , print());       // print functor created (constructor)
                                               // a copy created here (C1)

Теперь это полностью зависит от реализации, если копирование выполнено или нет. Стандарт позволяет этой широте исключать конструктор копирования, например, C3 может быть устранен.

Хороший способ управления поведением gcc здесь - это -fno-elide-constructors , который гарантирует, что код не исключает конструктор копирования

0 голосов
/ 18 августа 2010

Я бы сказал, что for_each создал копии функтора print (), который вызывает неявный конструктор копирования, определенный компилятором, который не появляется в вашем коде (не то же самое, что ваш определенный конструктор выше).

0 голосов
/ 18 августа 2010

Вы печатаете «Конструктор» только из конструктора по умолчанию.Экземпляры вашего типа также могут появиться в конструкторе копирования.Копии могут быть сделаны через стек вызовов.Если не указано иное, вы получаете конструктор копирования по умолчанию бесплатно.Вы можете добавить конструктор копирования, а также распечатать «Конструктор», если хотите это проверить.

Независимо от того, как он сконструирован, вы все равно увидите один-единственный деструктор, стреляющий и распечатывающий «Деструктор»».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...