我有一些C++11之前的代码,在这些代码中,我经常使用const
引用来传递像vector
这样的大参数。示例如下:
int hd(const vector<int>& a) {
return a[0];
}
我听说有了新的C++11特性,您可以按如下方式按值传递vector
,而不会影响性能。
int hd(vector<int> a) {
return a[0];
}
例如,this answer说
C++11的移动语义使得按值传递和返回更具吸引力,即使对于复杂的对象也是如此。
上述两个选项在性能方面是否真的相同?
如果是这样,什么时候像选项1那样使用常量引用比选项2更好?(即为什么我们仍然需要在C++11中使用常量引用)。
我问的一个原因是,常量引用会使模板参数的推导变得复杂,如果在性能方面与常量引用相同,那么只使用按值传递会容易得多。
发布于 2014-07-03 08:57:37
通过值传递的一般经验规则是,当您最终创建一个副本时。这就是说,与其这样做,不如:
void f(const std::vector<int>& x) {
std::vector<int> y(x);
// stuff
}
在你首先传递const-ref然后复制它的地方,你应该这样做:
void f(std::vector<int> x) {
// work with x instead
}
在C++03中,这在一定程度上是正确的,并且在移动语义中变得更加有用,因为当使用右值调用函数时,在通过val传递函数的情况下,副本可能会被移动替换。
否则,当您只想读取数据时,通过const
引用传递仍然是首选的、高效的方法。
发布于 2014-07-03 08:52:20
这有很大的不同。您将获得一个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)
C++11和右值引用的引入改变了返回像向量这样的对象的规则--现在你可以这样做了(不用担心有保证的副本)。虽然没有改变将它们作为参数的基本规则-你仍然应该通过常量引用来获取它们,除非你真的需要一个真正的复制-按值获取。
发布于 2014-07-03 10:45:36
C++11的移动语义使得按值传递和返回更具吸引力,即使对于复杂的对象也是如此。
但是,您给出示例是通过值传递的示例
int hd(vector<int> a) {
所以C++11对此没有影响。
即使您正确地声明了'hd‘以获取右值
int hd(vector<int>&& a) {
它可能比按值传递更便宜,但执行成功的移动(而不是简单的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
考虑下面的完整示例:
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.
}
作为一般规则:
如果目标需要可变副本,则为
https://stackoverflow.com/questions/24543330
复制相似问题