Ответ 1
Нити не имеют к этому никакого отношения, но порядок конструкторов/деструкторов блокировки может повлиять на вас.
Глядя на шаги низкого уровня, которые ваш код делает, с отсутствием копирования, один за другим (с использованием опции GCC -fno-elide-constructors):
- Построить
lock
. - Создайте временные аргументы
user_type
с(...)
. - Копировать-построить временное возвращаемое значение функции типа
user_type
, используя значение с шага 2. - Уничтожьте временную часть с шага 2.
- Уничтожьте
lock
. - Скопируйте конструкцию
user_type result
, используя значение с шага 3. - Уничтожьте временную часть с шага 3.
- Позже уничтожьте
result
.
Естественно, что при оптимизации оптимизации нескольких копий это будет просто:
- Построить
lock
. - Создайте объект
result
непосредственно с помощью(...)
. - Уничтожьте
lock
. - Позже уничтожьте
result
.
Обратите внимание, что в обоих случаях конструктор user_type
с (...)
защищен блокировкой. Любой другой конструктор конструктора или деструктор не может быть защищен.
запоздалые мысли
Я думаю, что наиболее вероятное место, где это может вызвать проблемы, находится в деструкторах. То есть, если ваш исходный объект, построенный с помощью (...)
, обрабатывает любой общий ресурс иначе, чем его копии, и делает что-то в деструкторе, которому требуется блокировка, тогда у вас есть проблема.
Естественно, это означало бы, что ваш объект плохо проектируется в первую очередь, поскольку копии не ведут себя как исходный объект.
Ссылка
В проекте С++ 11, 12.8.31 (аналогичная формулировка без всех "ходов" находится в С++ 98:
При выполнении определенных критериев реализация допускает опустить конструкцию копирования/перемещения класса объект, даже если конструктор copy/move и/или деструктор объекта имеют побочные эффекты. В таких случаях, реализация рассматривает источник и цель пропущенной операции копирования/перемещения как просто две разные способы обращения к одному и тому же объекту, а уничтожение этого объекта происходит в более поздние времена когда два объекта были бы уничтожены без оптимизации. Это разрешение копирования/перемещения операции, называемые копией, разрешены в следующих обстоятельствах (которые могут быть объединены с устранить несколько копий):
в операторе return в функции с типом возвращаемого класса, когда выражение является именем энергонезависимый автоматический объект (кроме функции или параметра catch-clause) с тем же cvunqualified тип как возвращаемый тип функции, операцию копирования/перемещения можно опустить при построении автоматический объект непосредственно в функции возвращает значение
параметр или параметр catch-clause), объем которого не выходит за пределы самого внутреннего (если есть), операция копирования/перемещения из операнда в исключение объект может быть опущен путем создания автоматического объекта непосредственно в объект исключения
когда объект временного класса, который не привязан к ссылке, будет скопирован/перемещен к объекту класса с тем же cv-неквалифицированным типом операция копирования/перемещения может быть опущена построение временного объекта непосредственно в цель пропущенной копии/перемещения
когда объявление исключения обработчика исключений объявляет объект того же типа (за исключением cv-qualification) в качестве объекта исключения, операцию копирования/перемещения можно опустить, рассматривая объявление исключения как псевдоним для объекта исключения, если значение программы будет не изменяться, кроме выполнения конструкторов и деструкторов для объекта, объявленного объявление исключения.
Точки 1 и 3 сотрудничают в вашем примере, чтобы исключить все копии.