C++进阶:重载下标运算符[]

我们使用数组时,通常使用下标运算符([])来索引数组的特定元素,但我们常用的自定义类型(结构struct,类class,枚举enum等)却不像数组那样有内置的下标运算符,所以我们需要重载下标运算符[].

目录结构:

├── ~/cpp/                # C++ 项目主目录
│       ├── StudentGrade.h        # StudentGrade类头文件
│ 		├── GradeMap.h            # GradeMap类实现
│	 	├── GradeMap.cpp          # GradeMap类实现
│ 		└── main.cpp              # 主程序文件
└──  README.md                    # 项目说明文档

在这里插入图片描述

注意:这个为伪代码,用于梳理逻辑. lamda表达式处为const auto& student

实现目的

在这里插入图片描述

就像数组那样, 当我们访问array的下标arrary[i]时,就能得到它所对应的值.

源文件

StudentGrade.h

#ifndef STUDENTGRADE_H
#define STUDENTGRADE_H
#include <string>
struct StudentGrade
{
    std::string m_name{};
    char m_grade{};
};                                                                                                                                                                                                                                                                                                                                                                    #endif  

GradeMap.h

#ifndef GRADEMAP_H
#define GRADEMAP_H
#include "StudentGrade.h"
#include <vector>
#include <string_view>
class GradeMap
{
private:
    std::vector<StudentGrade> m_map{};
public:
    GradeMap() = default;
    GradeMap(const std::vector<StudentGrade>& map)
        :m_map{ map }
    {}

    char& operator[](std::string_view name);
};

#endif

此处我用std::string_view name,而没有用std::string name,是因为std::string为了解决初始化(或复制)开销过大的问题,C++17 引入了std::string_view(位于 <string_view> 标头中)。它提供了对现有字符串(C 样式字符串、或其他)std::string_view的只读访问,而无需进行复制。

GradeMap.cpp

#include "GradeMap.h"
#include <string>

char& GradeMap::operator[](std::string_view name)
{
    auto found{ std::ranges::find_if(m_map.begin(), m_map.end(),
                            [name](const auto& student){ // this is lambda that captures name from the surronding scope
                                return (student.m_name == name);// so we can use name here
                            })};
    if (found != m_map.end())
    {
        return found->m_grade;
    }

    // emplace_back version (C++20 onward)
    // StudentGrade is an aggregate and emplace_back only works with aggregates as of C++20
    return m_map.emplace_back(std::string{name}).m_grade;

    // push_back version (C++17 or older)
    // m_map.push_back(StudentGrade{std::string{name}});
    // return m_map.back().grade;
}

return m_map.emplace_back(std::string{name}).m_grade;
其作用是在vector容器的第二个元素,也就是SudentGrade::grade,添加一个元素.并没有用到obj.push_back()和obj.back()的组合,原因是push_back()的开销太大了,详情如下:

// push_back 的方式:
StudentGrade temp(name, ’ '); // 1. 创建临时对象
m_map.push_back(temp); // 2. 拷贝到容器
// 或者
m_map.push_back(StudentGrade(name, ’ ')); // 创建临时对象再移动

// emplace_back 的方式:
m_map.emplace_back(name, ’ '); // 直接在容器内存中构造,无临时对象

main.cpp

#include "StudentGrade.h"
#include "GradeMap.h"
#include <iostream>


void class_implement_test()
{
    GradeMap grades{};

    grades["Joe"] = 'A';
    grades["Frank"] = 'B';

    std::cout << "Joe has a grade of " << grades["Joe"] << '\n';
    std::cout << "Frank has a grade of " << grades["Frank"] << '\n';

}

int main()
{
    class_implement_test();

    return 0;
}

功能演示

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值