Dan*_*hen 5 c++ performance c++11 c++17
我想编写一个通过移动或复制接收参数的模板函数。我使用的最有效的方法是:
void setA(A a)
{
m_a = std::move(a);
}
Run Code Online (Sandbox Code Playgroud)
在这里,当我们使用的是
A a;
setA(a); // <<---- one copy ctor & one move ctor
setA(std::move(a)); // <<---- two move ctors
Run Code Online (Sandbox Code Playgroud)
我最近发现以这种方式定义它,有两个功能:
void setA(A&& a)
{
m_a = std::move(a);
}
void setA(const A& a)
{
m_a = a; // of course we can so "m_a = std::move(a);" too, since it will do nothing
}
Run Code Online (Sandbox Code Playgroud)
会省很多!
A a;
setA(a); // <<---- one copy ctor
setA(std::move(a)); // <<---- one move ctor
Run Code Online (Sandbox Code Playgroud)
这很棒!对于一个参数...创建具有 10 个参数的函数的最佳方法是什么?!
void setAAndBAndCAndDAndEAndF...()
Run Code Online (Sandbox Code Playgroud)
任何人有任何想法?谢谢!
setA(A&& a)可以使用转发参考(也称为完美转发)将两个 setter 版本setA(const A& a)合并为一个版本:
template<typename A>
void setA(A&& a)
{
m_a = std::forward<A>(a);
}
Run Code Online (Sandbox Code Playgroud)
然后,编译器将根据值类别根据需要合成右值或左值引用版本。
这也解决了多值设置器的问题,因为将根据每个参数的值类别合成正确的设置器。
话虽如此,请记住 setter 只是常规函数;从技术上讲,当任何 setter 可以被调用时,该对象就已经构造完毕。在 的情况下setA,如果A有一个不平凡的构造函数,那么实例m_a将已经被(默认)构造并且setA实际上必须覆盖它。
这就是为什么在现代 C++ 中,重点通常不是移动与复制,而是就地构造与移动/复制。
例如:
struct A {
A(int x) : m_x(x) {}
int m_x;
};
struct B {
template<typename T>
B(T&& a) : m_a(std::forward<T>(a)) {}
A m_a;
};
int main() {
B b{ 1 }; // zero copies/moves
}
Run Code Online (Sandbox Code Playgroud)
除了更传统的“push”/“add”式调用之外,标准库还经常提供“emplace”式调用。例如,vector::emplace获取构造元素所需的参数,并在向量内构造一个元素,而无需复制或移动任何内容。
| 归档时间: |
|
| 查看次数: |
322 次 |
| 最近记录: |