2016-05-09 2 views
5

Here вы можете увидеть выполнение оператора присваивания копии с Самоконтроль назначения:Является ли оператором присваивания копий с копией и обменой идиомой и проверкой самоопределения?

String & operator=(const String & s) 
{ 
    if (this != &s) 
    { 
     String(s).swap(*this); //Copy-constructor and non-throwing swap 
    } 

    // Old resources are released with the destruction of the temporary above 
    return *this; 
} 

Это хорошо для себя задания, но плохо сказывается на производительности:

  1. как каждый раз, когда он проверяет, как если бы заявление (I не знаю, насколько это будет оптимально, учитывая предсказание ветви)
  2. Также мы теряем здесь копию elision для аргументов r

Так что я до сих пор не понимаю, буду ли я реализовывать 's operator=, как бы я его реализовал.

+0

Если вы не выполняете самопроверку, чем в случае примера присваивания: 'A = A;' значение объекта 'A' ​​будет удалено. Насколько я знаю, большая реализация операции оператора присваивания для самообучения –

+1

Почему это будет удалено? Вы можете реализовать его таким образом, чтобы он по-прежнему был безопасным, но вы не проверяете самоопределение. – Narek

+0

позволяет сказать, что 'A' содержит значения в куче. первым шагом будет удаление этих значений и добавление к нему значений rvalue. но поскольку эти значения совпадают, вы уже удалили их. –

ответ

5

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

String& String::operator=(String s) { // note passing by value! 

    std::swap(s, *this); // expected to juggle couple of pointers, will do nothing for self-assingment 
    return *this; 
} 

Также отметим, что более благотворно, чтобы принять аргумент по значению.

+1

Аргумент по значению уже является копией. Для самостоятельного назначения вы уже сделали плохое дело. Считайте, что вектор слишком велик. – Narek

+1

1) нет причин иметь 'tmp', если вы принимаете значение. 2) 'std :: swap', вероятно, приведет к бесконечной рекурсии. –

+0

@ T.C., Соглашайтесь с tmp. Артефакт предыдущей версии удалит. Но почему бесконечные рекурсии с обменом? Ожидается, что он будет специализирован для указателей String и juggle. – SergeyA

1

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

Я думаю, у вас есть себя в преждевременной оптимизации круга Вот.

Проверьте самоподключение -> самозапуск не нужен, если вы правильно написали код -> почему бы не написать swap явно, если вы имеете в виду? -> мы вернемся к квадрату.

Реально, я бы просто реализовал Allocator и не волноваться об этом.

Также мы проиграем здесь скопировать Пропуска для RValue аргументы

Я не думаю так.

#include <iostream> 

#define loud(x) std::cout << x << "\n"; 

struct foo 
{ 
    foo() { loud("default") } 
    ~foo() { loud("destruct") } 

    foo(const foo&) { loud("copy") } 
    foo(foo&&) { loud("move") } 

    foo & operator=(const foo & s) 
    { 
     if (this != &s) 
     { 
      loud("copy assign") 
     } 

     return *this; 
    } 
}; 

int main() 
{ 
    foo f; 
    foo g; 
    g = f; 
} 

Выходы:

default 
default 
copy assign 
destruct 
destruct 

Это с -fno-elide-constructors.


Вы утверждаете ветвь может быть проблемой, но выход сборки для -O2 показывает мне, что GCC даже не испускают код для operator= и просто выводит "copy assign" строку непосредственно. Да, я понял, что у меня упрощенный пример, но действительно - это неправильный конец сваи.

 Смежные вопросы

  • Нет связанных вопросов^_^