我有一些pre-C++ 11代码,其中我使用const引用传递大量参数,如vector'很多.一个例子如下:
int hd(const vector<int>& a) {
return a[0];
}
Run Code Online (Sandbox Code Playgroud)
我听说使用新的C++ 11功能,您可以vector按如下方式传递by值而不会出现性能命中.
int hd(vector<int> a) {
return a[0];
}
Run Code Online (Sandbox Code Playgroud)
例如,这个答案说
C++ 11的移动语义使得即使对于复杂对象,传递和返回值也更具吸引力.
上述两个选项在性能方面是否相同?
如果是这样,何时比选项2更好地使用const参考?(也就是为什么我们仍然需要在C++ 11中使用const引用).
我问的一个原因是const引用使模板参数的推导变得复杂,并且如果它与const引用性能相同,则仅使用pass-by-value会容易得多.
Rap*_*ptz 70
通过值传递的一般经验法则是,无论如何最终都要制作副本.也就是说,而不是这样做:
void f(const std::vector<int>& x) {
std::vector<int> y(x);
// stuff
}
Run Code Online (Sandbox Code Playgroud)
你首先传递一个const-ref 然后复制它,你应该这样做:
void f(std::vector<int> x) {
// work with x instead
}
Run Code Online (Sandbox Code Playgroud)
这在C++ 03中已经部分正确,并且随着移动语义变得更加有用,因为当使用rvalue调用函数时,副本可能被pass-by-val情况中的移动所取代.
否则,当你想要做的只是读取数据时,通过const引用传递仍然是首选的有效方法.
cub*_*l42 11
有一个很大的不同.你将获得一个vector内部数组的副本,除非它即将死亡.
int hd(vector<int> a) {
//...
}
hd(func_returning_vector()); // internal array is "stolen" (move constructor is called)
vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
hd(v); // internal array is copied (copy constructor is called)
Run Code Online (Sandbox Code Playgroud)
C++ 11和rvalue引用的引入改变了关于返回像vector这样的对象的规则 - 现在你可以这样做(不用担心保证副本).尽管如此,没有关于将它们作为参数改变的基本规则- 你仍然应该通过const引用来获取它们,除非你真的需要一个真正的副本 - 然后按值获取.
C++ 11的移动语义使得即使对于复杂对象,传递和返回值也更具吸引力.
但是,您提供的样本是按值传递的样本
int hd(vector<int> a) {
Run Code Online (Sandbox Code Playgroud)
所以C++ 11对此没有影响.
即使你已经正确宣布'hd'采取右值
int hd(vector<int>&& a) {
Run Code Online (Sandbox Code Playgroud)
它可能比按值传递更便宜,但执行成功的移动(与简单的std::move可能根本没有效果相反)可能比简单的传递参考更昂贵.vector<int>必须构建一个新的,它必须拥有内容的所有权a.我们没有必须分配新的元素数组并复制值的旧开销,但我们仍然需要传输数据字段vector.
更重要的是,在成功移动的情况下,a将在此过程中被销毁:
std::vector<int> x;
x.push(1);
int n = hd(std::move(x));
std::cout << x.size() << '\n'; // not what it used to be
Run Code Online (Sandbox Code Playgroud)
考虑以下完整示例:
struct Str {
char* m_ptr;
Str() : m_ptr(nullptr) {}
Str(const char* ptr) : m_ptr(strdup(ptr)) {}
Str(const Str& rhs) : m_ptr(strdup(rhs.m_ptr)) {}
Str(Str&& rhs) {
if (&rhs != this) {
m_ptr = rhs.m_ptr;
rhs.m_ptr = nullptr;
}
}
~Str() {
if (m_ptr) {
printf("dtor: freeing %p\n", m_ptr)
free(m_ptr);
m_ptr = nullptr;
}
}
};
void hd(Str&& str) {
printf("str.m_ptr = %p\n", str.m_ptr);
}
int main() {
Str a("hello world"); // duplicates 'hello world'.
Str b(a); // creates another copy
hd(std::move(b)); // transfers authority for b to function hd.
//hd(b); // compile error
printf("after hd, b.m_ptr = %p\n", b.m_ptr); // it's been moved.
}
Run Code Online (Sandbox Code Playgroud)
作为基本规则:
std::move(std::string("a") + std::string("b"))),