You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用基于范围的for循环访问shared_ptr包装的vector出现异常结果

为什么基于范围的for循环输出与vector存储内容不符?

我编写了如下C++代码,运行后发现基于范围的for循环输出和vector中存储的内容不一致:

#include <iostream>
#include <memory>
#include <vector>

using namespace std;

shared_ptr<vector<double>> get_ptr() {
    vector<double> v{1, 2, 3, 4, 5};
    return make_shared<vector<double>>(v);
}

int main() {
    auto vec = get_ptr();
    for (int i = 0; i<get_ptr()->size(); ++i) {
        std::cout << (*get_ptr())[i] << std::endl;
    }
    for (auto v: (*get_ptr())) {
        std::cout << v << std::endl;
    }
}

Ubuntu系统上的输出:

1
2
3
4
5
4.67913e-310
4.67913e-310
3
4
5

问题原因

  1. 每次调用get_ptr()都会生成全新的vector:get_ptr()函数每次被调用时,都会创建一个新的vector<double>实例,并返回指向该实例的shared_ptr。
  2. 范围for循环中临时对象的生命周期未被延长:在基于范围的for循环for (auto v: (*get_ptr()))中,(*get_ptr())会生成一个临时的vector对象。根据C++标准,绑定到范围for循环引用的临时对象,其生命周期不会被延长到循环结束——临时对象在循环初始化阶段结束后就会被销毁,后续循环中使用的迭代器会变成悬垂迭代器,访问这些迭代器指向的内存会导致未定义行为,输出垃圾值。

第一个普通for循环看似正常只是巧合:每次循环判断条件和访问元素时调用get_ptr(),都会生成一个新的、内容正确的vector,所以每次访问的都是新vector的有效元素,但这种写法非常低效且存在隐患。

解决方案

直接复用已经获取到的shared_ptr对象vec,避免重复调用get_ptr()生成临时对象:

修改后的main函数:

int main() {
    auto vec = get_ptr();
    // 复用vec,避免重复创建vector
    for (int i = 0; i < vec->size(); ++i) {
        std::cout << (*vec)[i] << std::endl;
    }
    // 用vec指向的vector遍历,不再生成临时对象
    for (auto v: (*vec)) {
        std::cout << v << std::endl;
    }
}

修改后两次循环都会访问同一个vector实例,输出结果会完全符合预期:

1
2
3
4
5
1
2
3
4
5

内容的提问来源于stack exchange,提问作者tesla1060

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 20:45:31