Почему ходы дороже, чем передача по const

#c #assembly #move #copy-constructor #lifetime

#c #сборка #переместить #copy-constructor #срок службы

Вопрос:

Я передаю несколько объектов в конструктор прямо перед тем, как закончится их время жизни.

 int main(){

    //I wanted to avoid short string optimization in this example.
    const std::string a(25,"a");
    const std::string b(25,"b");
    const std::string c(25,"c");

    Foo f{a,b,c};
}
  

Есть два варианта, которые я рассматривал для конструктора Foo.

constamp; (вызов конструктора копирования строки):

 Foo(const std::string amp; a,
    const std::string amp; b,
    const std::string amp; c)
:a(a)
,b(b)
,c(c)
{}
  

std::move (вызов конструктора перемещения строки):

 Foo(std::string a,
    std::string b,
    std::string c)
:a(std::move(a))
,b(std::move(b))
,c(std::move(c))
{}  
  

С -01 помощью on gcc 7 я получил следующие результаты:

  ------------- ----------------------- 
| constructor | assembly instructions |
 ------------- ----------------------- 
| constamp;      |                   192 |
| move        |                   264 |
 ------------- ----------------------- 
  

Почему constamp; меньше инструкций?
Я думал, что перемещение будет дешевле, чем создание новой строки с помощью конструктора копирования.

Каково эмпирическое правило для передачи переменных в качестве аргументов конструктора
, когда время жизни этих аргументов заканчивается?

Комментарии:

1. удалить const из a,b,c in main и параметры; и использовать move в вызове функции

Ответ №1:

Вы не вызываете конструктор перемещения. Ваши строки аргументов являются const . Итак, когда вы используете std::move их, результат const std::stringamp;amp; . Это не вызывает конструктор перемещения, который принимает подпись std::stringamp;amp; .

Комментарии:

1. Моя ошибка. Я звонил без const . То же самое происходит при передаче по значению и использовании перемещения.

Ответ №2:

Если компилятор не создает специальную версию конструктора для вызова main, он main все равно вызывает функцию с сигнатурой Foo(std::string a, std::string b, std::string c);

Если он не встроен или gcc не создает его клон, который фактически передает аргументы по-другому, код в определении функции не может изменить способ ее вызова.

Представьте, что определение конструктора было в отдельном файле и даже не было видно во время main компиляции, только прототип. Это похоже на то, что вы получаете, компилируя с помощью only -O1 .