移动省略优化
Move elision optimization
考虑一个类的两个实现:
struct S1
{
std::vector< T > v;
void push(T && x) { v.push_back(std::move(x)); }
void push(T const & x) { push(T(x)); }
void pop() { v.pop_back(); }
void replace(T && x) { pop(); push(std::move(x)); }
void replace(T const & x) { replace(T(x)); }
};
struct S2
{
std::vector< T > v;
void push(T x) { v.push_back(std::move(x)); }
void pop() { v.pop_back(); }
void replace(T x) { pop(); push(std::move(x)); }
};
S1
的push
重载正好表达了我想要的内容。S2
的push
是用一种不那么冗长的方式来表达它的一种方式。
但我担心有一个缺点与对象的过度移动构造有关。
对于某些t
(其中decltype(t)
是T&
),现代编译器能否将表达式std::move(T(std::move(t)))
简化为std::move(t)
?现代编译器能优化掉不必要的动作吗?或者这是标准所禁止的?
否,该省略是不合法的,除了under if优化之外。
现在,如果foo()
是一个返回T
的表达式,那么S{}.push(foo())
可以省略从foo()
的返回值到push
的变元的移动:只执行一次移动。
但如果我们使用S{}.push(std::move(foo())
,则显式std::move
阻断了省略的可能性。
一种通常更好的方法是基于位置的操作,而不是基于推送的操作。
template<class...Args>
void emplace(Args&&...args) {
v.emplace_back( std::forward<Args>(args)... );
}
这允许您将构造T
的参数传递给对象,并使其直接在接收器(矢量)中构造,而不是移动或复制到其中。
可选:
template<class...Args,
decltype(T(std::declval<Args&&>()...))* =0
>
void emplace(Args&&...args) {
v.emplace_back( std::forward<Args>(args)... );
}
如果您想要SFINAE支持。一条评论说"我们希望在这里构建一个T
",如果不明显的话,也是礼貌的。
相关文章:
- 空基优化子对象的地址
- 将对象移动到std::shared_ptr
- 何时在引用或唯一指针上使用移动语义
- 如何从具有移动语义的类对象中生成共享指针
- 关闭||运算符优化
- 将shared_ptr移动到<StructA>shared_ptr<变体<结构A、结构 B>>
- 返回值优化:显式移动还是隐式
- 编译器是否优化了默认移动构造函数?
- 标志以将IPDB和IOBJ文件从链接时间代码生成优化(LTCG)移动
- 按值返回堆栈上的变量是否优化为移动
- 从具有移动语义或返回值优化的函数返回值,但不返回复制构造函数
- RVO和NRVO优化+C++11移动操作员
- 移动省略优化
- 异常、移动语义和优化:任由编译器摆布 (MSVC2010)?
- c++11返回值优化或移动
- 将对以字符串形式返回文件内容的函数执行移动语义优化或返回值优化,我会从中受益吗
- 移动或命名返回值优化(NRVO)
- C++11移动构造函数优化
- 小字符串优化(SSO)和移动语义
- 可变模板与完美的转发没有优化移动语义