为什么在我的函数类型后使用引用运算符 (&) 允许我修改它返回的值?

Why Does Using the Reference Operator(&) After my Function Type Allow me to Modify the Value it Returns?

本文关键字:修改 允许我 返回 运算符 函数 我的 类型 引用 为什么      更新时间:2023-10-16

我正在创建我自己版本的向量容器(以STL向量容器为模式(,遇到了一个有趣的问题。我希望能够使用.at((函数为我的向量赋值,比如:

vector<int> myVec1 = {1, 1, 3, 4};
myVec1.at(1) = 2; //assigning a value using .at()

所以我做了一些实验,我发现如果我把.at((函数做成这样:

template <typename Type>
Type& My_vector<Type>::at(int const index) {            //notice the ampersand(&)
return *(array + index);
}

那么我就可以像在STL向量类中一样赋值了!我打感叹号是因为对我来说,这是一个惊喜。我的想法是;运算符将返回给定索引处的值的地址,并执行以下操作:

My_vector<int> myVec1 = {1, 1, 3, 4};
myVec1.at(1) = 2;

将myVec1的第二个元素的地址设置为2。然而,情况并非如此,相反,它会更改那里的值。这对我来说很好,因为我的目标是能够使用.at((赋值,但我的问题是,当我说这个函数应该在此时返回值的地址时,我的想法有什么缺陷?我的函数定义中的"与"运算符实际上是如何在这里工作的?我能说"它正在返回对给定索引处数组值的引用吗?"这似乎就是正在发生的事情,但哇,我认为我很好地掌握了&和*操作员在大多数情况下工作。下面是一个功能齐全的示例:

My_vector.h

#ifndef My_vector_h
#define My_vector_h
#include <cstring>
#include <type_traits>
#include <initializer_list>
template <typename Type>
class My_vector {
private:
Type* array;
int vector_size;
public:
//Copy Constructor
My_vector(std::initializer_list<Type> list) {
array = new Type[list.size() + 10];
vector_size = list.size();
memcpy(array, list.begin(), sizeof(Type) * list.size());
}
//Destructor
~My_vector() {delete [] array; array = nullptr;}
//Accessor .at()
int size() {return vector_size;}
Type& at(int const);
};
template <typename Type>
Type& My_vector<Type>::at(int const index) {
return *(array + index);
}
#endif /* My_vector_h */

main.cpp

#include <iostream>
#include "My_vector.h"
int main() {
My_vector<int> sampleVec = {1, 1, 3, 4};
for (int i = 0; i < sampleVec.size(); i++) {
std::cout << sampleVec.at(i) << " ";
}
std::cout << std::endl;
sampleVec.at(1) = 2;
for (int i = 0; i < sampleVec.size(); i++) {
std::cout << sampleVec.at(i) << " ";
}
std::cout << std::endl;
return 0;
}

输出:

1 1 3 4 
1 2 3 4 

为什么使用引用运算符(&(。。。

它不是"引用运算符"。它根本不是操作员。您已将返回类型声明为引用类型。Lvalue引用更具体。

那么我就可以像在STL向量类中一样赋值了!我打感叹号是因为对我来说,这是一个惊喜。

如果您查看函数中标准库向量的返回类型,您会发现它还返回了一个引用。

我的想法是;操作员将返回给定索引处的值的地址

没有。它返回一个引用。(尽管,从技术上讲,编译器确实可以通过使用内存地址来实现间接(

并且[myVec1.at(1) = 2;]将myVec1的第二个元素的地址设置为2。

您的假设错误。指定给引用就是指定给引用的对象(不能将引用设置为引用另一个对象(。

我可以说"它正在返回对给定索引处数组值的引用吗?">

是。

国际上可用的符号数量有限,因此c++必须在不同的地方重用一些符号。

在"与"的情况下,有三个地方使用它。

  1. 与号(的地址(运算符,用于表达式中检索变量的地址,是星形或解引用运算符的倒数。例如:

    int i = 1;
    int* pi = &i; // store the address of i in pi
    int j = *pi; // dereference the pi pointer and store the value in j
    
  2. 引用类型,在类型声明中使用它来声明一个类似指针但不需要解引用且不能为null的类型。例如:

    int i = 1;
    int & ri = i; // take a reference to i in variable ri
    int j = ri; // store the value of the referenced variable in j
    
  3. 按位和运算符,这对两个数字进行二进制和运算。例如:

    int i = 3;
    int j = 2;
    int k = i & j; // set k to 3 AND 2
    

这两个运算符也可以在类中重载以执行其他操作(尽管应该谨慎使用(。