Это зависит от компилятора. В этом случае стандарт требует, чтобы был хотя бы один вызов конструктора. А именно, строительство t
.
Но стандарт допускает возможность двух других: Move-строительство выходного значения foo
из t
, и вселения строительство s
от выходного значения foo
. Большинство достойных компиляторов откажутся от этих конструкторов, построив t
непосредственно в памяти для s
. Эта оптимизация становится возможной, поскольку стандарт позволяет этим конструкторам не вызываться, если компилятор не хочет этого делать.
Это называется копирование/перемещение «элиция».
Если это так, то в функции я даже не возвращаю ссылку rvalue, так как компилятор может вызвать конструктор перемещения?
Вы, кажется, трудясь в заблуждение, что &&
означает «движение», и что, если там нет &&
где-то, то движение не может произойти. Или для этого строительства требуется move
, что также неверно.
C++ указан таким образом, что определенные типы выражений в определенных местах считаются действительными для перемещения. Это означает, что значение или ссылка попытаются привязать к параметру &&
перед привязкой к параметру &
. Например, временные ряды будут предпочтительно связываться с параметром &&
до const&
. Вот почему временные элементы, используемые для построения значений этого типа, будут перемещены.
Если у вас есть функция, которая возвращает значение некоторого типа T
, и выражение возвращаемого имеет вид return x
, где x
является именованным переменным типа T
автоматической продолжительности хранения (т.е. параметр функции или стек переменным), то стандарт требует, чтобы это возвращаемое выражение перемещало конструкцию возвращаемого значения от x
.
Возвращаемое значение foo
является временным. Правила C++ требуют, чтобы временные файлы связывались с параметрами &&
до const&
. Таким образом, вы получаете конструкцию перемещения в s
.
Что делать, если мы предполагаем, что компилятор не делает никакой оптимизации? – WhatABeautifulWorld
@WhatABeautifulWorld: Тогда это будет один конструктор, который, как я сказал, произойдет, плюс два дополнительных, которые, как я сказал, являются необязательными. –
Мне нужно изменить определение функции для foo, чтобы его можно было переместить? Я думаю: string && foo() {...} В противном случае, как мог компилятор узнать? Строка - всего лишь пример, на самом деле у меня есть свой собственный объект ... – WhatABeautifulWorld