Оптимизация перемещения или именованного возвращаемого значения (NRVO)?
Допустим, у нас есть следующий код:
std::vector<int> f()
{
std::vector<int> y;
...
return y;
}
std::vector<int> x = ...
x = f();
Кажется, у компилятора есть два подхода:
(a) NRVO: уничтожить x, затем построить f () вместо x.
(b) Перемещение: построить f () во временном пространстве, переместить f () в x, уничтожить f().
Является ли компилятор свободным для использования любого из подходов в соответствии со стандартом?
1 ответ
Компилятор может NRVO во временное пространство или переместить конструкцию во временное пространство. Оттуда он будет двигаться назначить x
,
Обновить:
Каждый раз, когда у вас возникает желание оптимизировать с помощью ссылок на rvalue, и вы не уверены в результатах, создайте себе пример класса, который отслеживает его состояние:
- построенный
- построено по умолчанию
- переехала из
- подорванный
И проведите этот класс через ваш тест. Например:
#include <iostream>
#include <cassert>
class A
{
int state_;
public:
enum {destructed = -2, moved_from, default_constructed};
A() : state_(default_constructed) {}
A(const A& a) : state_(a.state_) {}
A& operator=(const A& a) {state_ = a.state_; return *this;}
A(A&& a) : state_(a.state_) {a.state_ = moved_from;}
A& operator=(A&& a)
{state_ = a.state_; a.state_ = moved_from; return *this;}
~A() {state_ = destructed;}
explicit A(int s) : state_(s) {assert(state_ > default_constructed);}
friend
std::ostream&
operator<<(std::ostream& os, const A& a)
{
switch (a.state_)
{
case A::destructed:
os << "A is destructed\n";
break;
case A::moved_from:
os << "A is moved from\n";
break;
case A::default_constructed:
os << "A is default constructed\n";
break;
default:
os << "A = " << a.state_ << '\n';
break;
}
return os;
}
friend bool operator==(const A& x, const A& y)
{return x.state_ == y.state_;}
friend bool operator<(const A& x, const A& y)
{return x.state_ < y.state_;}
};
A&& f()
{
A y;
return std::move(y);
}
int main()
{
A a = f();
std::cout << a;
}
Если это поможет, поместите операторы печати в специальные элементы, которые вас интересуют (например, конструктор копирования, конструктор перемещения и т. Д.).
Между прочим, если это не поможет вам, не волнуйтесь. Это тоже для меня. Таким образом, этот конкретный дизайн (возвращающий ссылку на локальную переменную) не является хорошим. В вашей системе вместо segfaulting может выводиться "A уничтожено". Это было бы еще одним признаком того, что вы не хотите этого делать.