c++的引用

发布于:2025-06-06 ⋅ 阅读:(14) ⋅ 点赞:(0)

示例

方式1:
std::vector<PjOpd> _expr_opds; 
std::vector<PjOpd> _pj_opds;
auto &opd = _expr_opds[expr_id];
_pj_opds.push_back(opd);
方式2:
std::vector<PjOpd> _expr_opds; 
std::vector<PjOpd> _pj_opds;
auto opd = _expr_opds[expr_id];
_pj_opds.push_back(opd);
两种实现方式的差别?

分析

你提出的两个代码片段(**方式1 和 方式2**)在语义和行为上有显著的区别,尤其是在性能、对象拷贝以及后续修改对原数据的影响方面。

---

## 🧪 一、代码回顾

### ✅ 方式1:使用引用 `auto &`

```cpp
std::vector<PjOpd> _expr_opds; 
std::vector<PjOpd> _pj_opds;

auto &opd = _expr_opds[expr_id];  // 引用
_pj_opds.push_back(opd);         // 拷贝进新 vector
```

### ✅ 方式2:不使用引用 `auto`

```cpp
std::vector<PjOpd> _expr_opds; 
std::vector<PjOpd> _pj_opds;

auto opd = _expr_opds[expr_id];  // 拷贝构造
_pj_opds.push_back(opd);        // 再次拷贝进新 vector
```

---

## 📊 二、对比分析

| 特性 | 方式1(`auto &`) | 方式2(`auto`) |
|------|------------------|----------------|
| `opd` 类型 | `PjOpd&`(引用) | `PjOpd`(值拷贝) |
| 是否从 `_expr_opds` 中拷贝元素? | 否(只是引用) | 是(一次拷贝) |
| `push_back` 是否再次拷贝? | 是(两次拷贝总) | 是(两次拷贝总) |
| 性能影响 | 更高效(避免一次拷贝) | 多一次拷贝,效率略低 |
| 修改 `opd` 是否影响 `_expr_opds`? | 是(因为是引用) | 否(因为是拷贝) |
| 安全性 | 若 `_expr_opds` 被修改或重新分配内存,引用可能失效 | 更安全,与原始 vector 无关 |

---

## 🔍 三、详细解释

### ✅ 方式1:`auto &opd = _expr_opds[expr_id];`

- 这是一个 **引用绑定到 `_expr_opds` 中的某个元素**;
- 然后调用 `_pj_opds.push_back(opd)` 时,会将该元素 **拷贝一份** 到 `_pj_opds`;
- 所以总共发生了一次拷贝(不是两次);
- 如果你之后修改了 `opd`,那么 `_expr_opds[expr_id]` 的值也会被修改;
- 适用于:你想操作原始数据,并将其拷贝到另一个容器中;

### ✅ 方式2:`auto opd = _expr_opds[expr_id];`

- 这是一个 **拷贝构造**,把 `_expr_opds[expr_id]` 的值拷贝了一份到局部变量 `opd`;
- 然后再通过 `push_back(opd)` 把这个拷贝再拷贝一份到 `_pj_opds`;
- 所以总共发生了 **两次拷贝**;
- 修改 `opd` 不会影响 `_expr_opds`;
- 适用于:你想操作副本,不影响原始数据;

---

## 📌 四、推荐写法(更高效)

如果你只打算拷贝一次,可以这样写:

```cpp
_pj_opds.push_back(_expr_opds[expr_id]);
```

这等价于方式1的效果,但更简洁,也避免了中间变量的冗余。

---

## 🧠 五、何时选择哪种方式?

| 使用场景 | 推荐方式 |
|----------|----------|
| 只想拷贝一次,不需要修改原 vector 中的数据 | `push_back(_expr_opds[expr_id])` |
| 需要修改原 vector 中的对象 | 方式1(`auto &opd`) |
| 想操作副本,不影响原数据 | 方式2(`auto opd`) |

---

## ✅ 六、总结表格

| 对比维度 | 方式1(引用) | 方式2(值拷贝) |
|----------|---------------|----------------|
| 是否拷贝原始数据 | 否 | 是 |
| push_back 拷贝次数 | 1 次 | 2 次 |
| 修改 `opd` 是否影响 `_expr_opds` | 是 | 否 |
| 性能 | 更优 | 略差 |
| 安全性 | 注意 vector 扩容导致引用失效 | 更安全 |
| 推荐使用 | 当需要操作原始数据时 | 当只需要副本时 |