Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[52.14.8.34] |
|
Сообщ.
#1
,
|
|
|
Собственно сабж. Умеют ли современные компиляторы такое? Т.е. есть
1.cpp std::vector<int> f() { std::vector<int> v; //... return v; } 2.cpp std::vector<int> v = f(); Будут ли лишние вызовы конструктора копирования? |
Сообщ.
#2
,
|
|
|
Цитата shm @ Будут ли лишние вызовы конструктора копирования? А ты поставь вместо вектора std::unique_ptr и увидишь. |
Сообщ.
#3
,
|
|
|
Олег М, меня интересует общая тенденция, а не как реализовано у конкретного компилятора с конкретными настройками.
|
Сообщ.
#4
,
|
|
|
А что, разве общая тенденция не такая, чтоб использовать move-конструктор при return? Хотя, по-любому, я там всегда делаю std::move. Так, на всякий случай.
|
Сообщ.
#5
,
|
|
|
Цитата Олег М @ отя, по-любому, я там всегда делаю std::move. Так, на всякий случай. Надо ли писать return std::move(local_var)? Но в данном случае это оффтоп. |
Сообщ.
#6
,
|
|
|
Цитата shm @ Надо ли писать return std::move(local_var)? Но в данном случае это оффтоп Может и оффтоп. Но единственное, что я понял – что лучше всегда делать move. А вообще, такое поведение как–то может зависеть от единиц трансляции, в принципе? Т.е. я переношу функцию, которая возвращает unique_ptr в другой файл и код перестает компилироваться? |
Сообщ.
#7
,
|
|
|
Раздел 12.8.3 стандарта (N4618) [class.copy.elision]:
Цитата When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object. If the first parameter of the selected constructor is an rvalue reference to the object’s type, the destruction of that object occurs when the target would have been destroyed; otherwise, the destruction occurs at the later of the times when the two objects would have been destroyed without the optimization. This elision of copy/move operations, called copy elision , is permitted in the following circumstances (which may be combined to eliminate multiple copies): (1.1) in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function parameter or a variable introduced by the exception-declaration of a handler (15.3)) with the same type (ignoring cv-qualification) as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function call’s return object — (1.2) in a throw-expression (5.17), when the operand is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost enclosing try-block (if there is one), the copy/move operation from the operand to the exception object (15.1) can be omitted by constructing the automatic object directly into the exception object — (1.3) when the exception-declaration of an exception handler (Clause 15) declares an object of the same type (except for cv-qualification) as the exception object (15.1), the copy operation can be omitted by treating the exception-declaration as an alias for the exception object if the meaning of the program will be unchanged except for the execution of constructors and destructors for the object declared by the exception-declaration. [ Note: There cannot be a move from the exception object because it is always an lvalue. —end note ] Таким образом: а) Это должно работать между модулями в том числе - ссылка на переменную, в которой можно разместить результат, передаётся скрытым параметром функции. б) Запись return std::move(a); - это отключение RVO/copy elision. К слову, анализатор clang tidy на такие вещи матерится. |
Сообщ.
#8
,
|
|
|
Flex Ferrum, спс.
Добавлено Цитата Flex Ferrum @ в которой можно разместить результат, передаётся скрытым параметром функции. Я правильно понимаю, что если нет возможности использовать RVO, то компилятор создаст временный объект и передаст по ссылке? |
Сообщ.
#9
,
|
|
|
Цитата shm @ Я правильно понимаю, что если нет возможности использовать RVO, то компилятор создаст временный объект и передаст по ссылке? Как-то так, да, если я тебя правильно понял. Место, где размещать результат выполнения функции, всё равно ведь как-то передаётся в вызов. Просто с copy elision запись типа: std::string Foo(...) { std::string result("a"); result += "b"; return result; } сразу разместит result в скоупе вызывающей функции. А без RVO - будет выполнено копирование из временной переменной в возвращаемое значение. |