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

时间:2018-10-28 20:38:55

标签: c++

我正在创建自己的矢量容器版本(以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 

2 个答案:

答案 0 :(得分:2)

  

为什么使用引用运算符(&)...

它不是“引用运算符”。它根本不是运算符。您已将返回类型声明为引用类型。左值引用更具体。

  

然后我就可以像在STL向量类中那样分配值!我加上了感叹号,因为对我来说,这是一个惊喜。

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

  

我的想法是,&运算符的这种使用将返回给定索引处的值的地址

不是。它返回一个参考。 (尽管从技术上讲,编译器确实可以通过使用内存地址来实现间接寻址)

  

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

您错误地假设。分配给引用是对引用对象的分配(不可能将引用设置为引用另一个对象)。

  

我可以说“它正在返回给定索引处的数组值吗?”

是的

答案 1 :(得分:1)

由于国际上可用的符号数量有限,因此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
    

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