#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
inmain
и параметры; и использовать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
.