fsc*_*can 8 c++ parameter-passing rvalue-reference c++11
考虑这些类:
#include <iostream>
#include <string>
class A
{
std::string test;
public:
A (std::string t) : test(std::move(t)) {}
A (const A & other) { *this = other; }
A (A && other) { *this = std::move(other); }
A & operator = (const A & other)
{
std::cerr<<"copying A"<<std::endl;
test = other.test;
return *this;
}
A & operator = (A && other)
{
std::cerr<<"move A"<<std::endl;
test = other.test;
return *this;
}
};
class B
{
A a;
public:
B (A && a) : a(std::move(a)) {}
B (A const & a) : a(a) {}
};
Run Code Online (Sandbox Code Playgroud)
在创建a时B,我总是有一个最佳前向路径A,一个是rvalues,一个是lvalues.
是否可以使用一个构造函数实现相同的结果?在这种情况下,这不是一个大问题,但是多个参数呢?我需要参数列表中每个可能出现的左值和右值的组合.
这不仅限于构造函数,还适用于函数参数(例如setter).
注意:这个问题严格来说class B; class A存在只是为了可视化复制/移动调用的执行方式.
"按价值"方法是一种选择.它不像你拥有的那样最优,但只需要一次重载:
class B
{
A a;
public:
B (A _a) : a(move(_a)) {}
};
Run Code Online (Sandbox Code Playgroud)
对于左值和左值,成本是1个额外的移动构造,但这对于prvalues(1个移动)仍然是最佳的."xvalue"是使用std :: move强制转换为右值的左值.
您还可以尝试"完美转发"解决方案:
class B
{
A a;
public:
template <class T,
class = typename std::enable_if
<
std::is_constructible<A, T>::value
>::type>
B (T&& _a) : a(std::forward<T>(_a)) {}
};
Run Code Online (Sandbox Code Playgroud)
这将使您回到最佳的复制/移动结构数.但是你应该约束模板构造函数,使它不是过于通用.您可能更喜欢使用is_convertible而不是is_constructible,就像我上面所做的那样.这也是一个构造函数解决方案,但是当您添加参数时,您的约束变得越来越复杂.
注意:上面需要约束的原因是因为没有,客户端B在查询时会得到错误的答案std::is_constructible<B, their_type>::value.如果没有适当的约束,它将错误地回答为真B.
我想说这些解决方案都不会比其他解决方案更好.这里有工程权衡.
| 归档时间: |
|
| 查看次数: |
1065 次 |
| 最近记录: |