通过值或引用传递构造函数参数
Passing constructor arguments by value or by reference
只是一个关于这样一个函数的快速问题:
class Test {
public:
Test(vector<int>& v) {
v_ = v;
}
private:
std::vector<int> v_;
};
使用Test(vector<int>& v)
和Test(vector<int> v)
有什么区别?我似乎知道第一个应该更快,因为它是通过引用传递的。但我不确定是否还有其他不同之处。
不同之处在于,Test(vector<int>& v)
(顺便说一句,它是一个左值引用)v指的是原始对象,而Test(vector<int> v)
有一个副本。下面的示例代码演示了int
和普通函数的区别(注意,对于int
,按值传递实际上更快!):
#include <iostream>
int global_i;
void pass_by_value(int i)
{
std::cout << "pass by value:n";
std::cout << "initially: i = " << i << ", global_i = " << global_i << "n";
i++;
std::cout << "after i++: i = " << i << ", global_i = " << global_i << "n";
global_i++;
std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "n";
}
void pass_by_reference(int& i)
{
std::cout << "pass by reference:n";
std::cout << "initially: i = " << i << ", global_i = " << global_i << "n";
i++;
std::cout << "after i++: i = " << i << ", global_i = " << global_i << "n";
global_i++;
std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "n";
}
void pass_by_const_reference(int const& i)
{
std::cout << "pass by const reference:n";
std::cout << "initially: i = " << i << ", global_i = " << global_i << "n";
// i++; not allowed!
// std::cout << "after i++: i = " << i << ", global_i = " << global_i << "n";
global_i++;
std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "n";
}
int main()
{
global_i = 1;
pass_by_value(global_i);
global_i = 1;
pass_by_reference(global_i);
global_i = 1;
pass_by_const_reference(global_i);
}
它的输出是:
pass by value:
initially: i = 1, global_i = 1
after i++: i = 2, global_i = 1
after global_i++: i = 2, global_i = 2
pass by reference:
initially: i = 1, global_i = 1
after i++: i = 2, global_i = 2
after global_i++: i = 3, global_i = 3
pass by const reference:
initially: i = 1, global_i = 1
after global_i++: i = 2, global_i = 2
如你所见,在按值调用中,实参和传递的变量是完全分开的。增加参数不会改变传递的变量,增加传递的变量也不会改变参数。另一方面,使用引用传递时,实参只提供对传递的变量的访问:您增加哪个变量并不重要,因为实际上它们是相同的。通过const引用传递,它们也是一样的,但是不允许对参数进行修改(但是有一些方法可以解决这个问题)。然而,参数仍然会反映对传递的变量的任何更改。
这些是功能上的差异。然而,有更多的区别:对于按值传递和按const引用传递,您可以使用右值,如call_by_value(2)
或call_by_const_reference(2)
。对于按值调用,发生的事情很明显:参数获得值2,仅此而已。然而,对于const引用,需要一个对象(例如,可以在函数中获取该对象的地址)。因此,在这种情况下,将创建一个临时对象。对于非const引用调用,不能传递右值。
c++ 11添加了另一种类型,即右值引用。用&&
代替&
表示。在函数内部,它们的行为与普通的(左值)引用完全相同,但它们的不同之处在于它们可以绑定到右值,即使它们不是const。而且,如果使用它们作为返回类型,调用表达式将是右值类型,就像您返回了一个值一样。特别是,您不能将返回右值引用的函数的结果传递给期望左值引用的函数,就像您不能对字面量2那样做。
您的代码中没有右值引用,只是大量不必要的复制。
然而,既然我们在这个话题上,这里是用move语义写这个的正确方法:
Test(std::vector<int> v) // by value!
: v_(std::move(v))
{
}
在11之前的世界中,次佳方法是通过const-reference获取实参并复制它:
Test(std::vector<int> const & v)
: v_(v)
{
}
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- 在按值调用 (c++) 中转发构造函数参数
- 如何使用 swig 修改类构造函数以保留对其中一个构造函数参数的引用?
- 如何在构造函数参数中初始化"std::set"?
- 何时应在构造函数参数中使用 const C++?
- 使用模板化结构作为构造函数参数
- 使用 lambda 作为构造函数参数是否需要C++ 17?
- 如何使输入文本文件成为构造函数参数?c++
- shared_ptr构造函数参数是否应按值传递
- 是否允许使用初始值设定项列表将const数组引用实例化为构造函数参数
- 复制构造函数参数为0
- 用作成员构造函数参数的函数的求值顺序
- 结构中的默认成员值或默认构造函数参数
- C++将引用成员绑定到构造函数参数
- 如何通过可变参数模板将多个构造函数参数转发到数组初始值设定项列表?
- 模板函数指针参数与构造函数参数
- 如何将 std::string 作为构造函数参数传递,并将其保存的 C 字符串存储在 void 指针中?
- 如何基于构造函数参数模板化类成员函数的代码
- 将派生类构造函数参数传递给受保护的成员
- 如何根据构造函数参数使用超类类型初始化成员变量?