Upload
takashi-hoshino
View
78
Download
3
Embed Size (px)
Citation preview
Rvalue reference で受けるとき
•渡された中身は move して良い
3
struct Widget {
std::string name;
std::shared_ptr<SomeDataStructure> p;
Widget(Widget&& rhs)
: name(std::move(rhs.name))
, p(std::move(rhs.p)) {
}
};
Universal reference で受けるとき
•渡された中身は forward する
4
struct Widget {
std::string name;
template <typename T>
void setName(T&& newName) {
name = std::forward<T>(newName);
}
};
Universal reference を std::move するのはやめた方が良い
6
struct Widget {
std::string name;
template <typename T>
void setName(T&& newName) {
name = std::move(newName);
}
};
std::string getWidgetName() {
//...
}
int main() {
Widget w;
auto n = getWidgetName();
w.setName(n);
// n is unknown now.
}
Overload する手段がある
• const lvalue reference と rvalue reference
•欠点• コードが増える
• 効率が悪くなる(ことがある)
• 引数の数が増えると爆発する (2^n)
7
struct Widget {
void setName(const std::string& newName) {
name = newName;
}
void setName(std::string&& newName) {
name = std::move(newName);
}
}
w.setName("Adala Novak");
可変長引数の場合
• Universal reference にせざるをえない
8
template <class T, class... Args>
shared_ptr<T> make_shared(Args&&... args);
template <class T, class... Args>
unique_ptr<T> make_unique(Args&&... args);
std::move や std::forward は最後に 1 回のみ使う
9
template <typename T>
void setSignText(T&& text) {
sign.setText(text);
auto now = std::chrono::system_clock::now();
signHistory.add(now, std::forward<T>(text));
}
std::move_if_noexcept
•例外が飛ぶ可能性のある関数に渡すときはmove しない
10
// cppreference
template<class T>
constexpr typename std::conditional<
!std::is_nothrow_move_constructible<T>::value &&
std::is_copy_constructible<T>::value,
const T&,
T&&
>::type move_if_noexcept(T& x);
Rvalue reference を値返しするとき• std::move() を使って return すると move をサポートしていない場合に copy constructor でコピーされる
• std::move() 使わないと強制コピー
11
Matrix operator+(Matrix&& lhs, const Matrix& rhs)
{
lhs += rhs;
return std::move(lhs);
}
Matrix operator+(Matrix&& lhs, const Matrix& rhs)
{
lhs += rhs;
return lhs; // copy
}
Universal reference を値返しするとき•同様に std::forward を使う
•使わないと強制コピー
12
template <typename T>
Fraction reduceAndCopy(T&& frac) {
frac.reduce();
return std::forward<T>(frac);
}
Local object を値返しするとき
• RVO (return value optimization) される or
• Local object を return するとき rvalue として扱われる
13
Widget makeWidget() {
Widget w;
// ...
return w;
}
Widget makeWidget() {
Widget w;
// ...
return std::move(w); // don't do this!
}