引用和值之间的差异。
C++ 的一个特点是它区分引用和值。许多其他语言不这样做。假设你有一个向量:
std::vector<int> v1 = {1, 2, 3};
创建此向量的深层副本非常简单:
auto copy_of_v1 = v1;
我们可以通过更改copy_of_v1来证明这一点:
std::cout << (v1 == copy_of_v1) << '\n'; // Prints 1, for true
copy_of_v1[1] = 20; // copy_of_v1 == {1, 20, 3} now
std::cout << (v1 == copy_of_v1) << '\n'; // Prints 0, for false
参考用例。
引用具有三个主要用例:
- 通过存储/使用参考来避免复制
- 从函数中获取附加信息(通过向其传递引用,并让它修改引用)
- 编写数据结构/容器类
我们已经看到了第一个案例,让我们看看另外两个案例。
使用引用来编写修改其输入的函数。假设您想使用+= 添加将元素附加到向量的功能。运算符是一个函数,因此如果要修改向量,则需要对其进行引用:
// We take a reference to the vector, and return the same reference
template<class T>
std::vector<T>& operator +=(std::vector<T>& vect, T const& thing) {
vect.push_back(thing);
return vect;
}
这允许我们将元素附加到向量中,就像它是一个字符串一样:
int main() {
std::vector<int> a;
((a += 1) += 2) += 3; // Appends 1, then 2, then 3
for(int i : a) {
std::cout << i << '\n';
}
}
如果我们不通过引用获取向量,函数将无法更改它。这意味着我们将无法附加任何内容。
使用引用来编写容器。
引用使在 C++ 中编写可变容器变得容易。当我们想要提供对容器中某些内容的访问时,我们只需返回对它的引用。这提供了对元素的直接访问,甚至是基元。
template<class T>
class MyArray {
std::unique_ptr<T[]> array;
size_t count;
public:
T* data() {
return array.get();
}
T const* data() {
return array.get();
}
MyArray() = default; // Default constructor
MyArray(size_t count) // Constructs array with given size
: array(new T[count])
, count(count) {}
MyArray(MyArray const& m) // Copy constructor
: MyArray(count) {
std::copy_n(m.data(), count, data();
}
MyArray(MyArray&&) = default;// Move constructor
// By returning a reference, we can access elements directly
T& operator[](size_t index) {
return array[index];
}
};
现在,当使用MyArray 时,我们可以直接更改和修改元素,即使它们是图元:
MyArray<int> m(10); // Create with 10 elements
m[0] = 1; // Modify elements directly
m[0]++; // Use things like ++ directly