Есть ли преимущество в использовании ссылочного аргумента в этой функции? - PullRequest
2 голосов
/ 06 октября 2009

Я определил следующий класс:

class Action
{
    public: 
    Action(){ _bAllDone = false; }

    void AddMove( Move & m );
    private:
        std::deque<Move> _todo;
        bool _bAllDone;
};

Элемент AddMove определяется следующим образом:

void Action::AddMove( Move & m )
{ 
    _todo.push_back( m ); 
}

Я заметил, что без аргумента ссылки на эту функцию конструктор копирования вызывался дважды, тогда как с аргументом ссылки он вызывался только один раз. Является ли вызов конструктора копирования только один раз, а не дважды хорошей причиной для использования ссылочного аргумента?

Ответы [ 3 ]

17 голосов
/ 06 октября 2009

Предполагается, что класс deque в STL хранит копию элемента, который вы передаете его методу push_back. Вот откуда появился один конструктор копирования.

Если вы избавитесь от ссылки в addMove (), вы сначала получите копию параметра (и, следовательно, один вызов конструктора копирования), а затем, когда вы вернетесь назад, вы получите вторую копию.

Двойной вызов конструктора копирования является расточительным, поэтому ссылка предпочтительнее. Однако вы должны объявить параметр addMove () как константную ссылку, чтобы указать вызывающей стороне, что элемент не будет изменен. При таком заверении (при условии, что вы не нарушаете его), безопасно передавать объект по ссылке, не беспокоясь и не платя штраф за копию объекта.

4 голосов
/ 06 октября 2009

Похоже, большое преимущество для меня. Все может стать очень медленным, если вы многократно выполняете многократные добавления. Фактический объем работы будет зависеть от определения Move и его конструктора копирования. И небольшие изменения могут иметь серьезные последствия для производительности. В любом случае, передача копией все равно будет вдвое больше работы.

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

0 голосов
/ 06 октября 2009

Это должно быть ссылкой, иначе вы получите ненужную (и потенциально неправильную) копию аргумента. Он также должен быть const, иначе вы будете излишне ограничивать своих абонентов.

Обратите внимание, что имена с начальным подчеркиванием зарезервированы для языковой реализации, поэтому ваша программа на самом деле "неопределена".

НТН

...