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

如何用std::shared_ptr共享非连续的内存区间?

实现非连续内存区间的共享方案

std::shared_ptr本身设计用于管理单一连续内存块(或单个对象),没法直接让它同时管理多个非连续的内存区间,这也是你遇到“无法获取float*类型右值的地址”报错的根本原因——它只接受单个原始指针关联控制块,无法绑定分散的多段指针。

下面是几种可行的实现思路:

1. 用多个shared_ptr分别管理各连续段

非连续区间本质是多个连续子段的组合,直接为每个子段创建独立的shared_ptr,通过捕获原数组的shared_ptr来共享所有权,避免原内存提前释放。示例代码:

#include <memory>
#include <vector>

int main() {
    auto arr = std::make_shared<std::vector<float>>(100); // 原数组
    auto& vals = *arr;

    // 管理索引2-5的连续段(长度4)
    std::shared_ptr<float> seg1(vals.data() + 2, [arr](float*){});
    // 管理索引70至末尾的连续段(长度30)
    std::shared_ptr<float> seg2(vals.data() + 70, [arr](float*){});

    // 使用seg1和seg2访问对应区间,原数组生命周期由所有shared_ptr共同维护
    return 0;
}

这里的自定义删除器为空逻辑,因为原数组的销毁权已经交给arr,只要seg1或seg2存在,arr的引用计数就不会归零,原数组不会被释放。

2. 自定义视图类封装非连续区间

如果需要对外提供统一的数组式访问接口,可以编写自定义视图类,内部持有原数组的shared_ptr,同时保存各非连续段的起始索引和长度,对外屏蔽非连续的细节:

#include <memory>
#include <vector>
#include <stdexcept>

struct NonContiguousView {
    using ElementType = float;
    std::shared_ptr<std::vector<ElementType>> arr;
    std::vector<std::pair<size_t, size_t>> segments; // 每个元素为(起始索引, 段长度)

    // 构造函数:传入原数组shared_ptr和非连续段范围
    NonContiguousView(std::shared_ptr<std::vector<ElementType>> ptr, 
                      std::initializer_list<std::pair<size_t, size_t>> segs)
        : arr(std::move(ptr)) {
        for (auto& seg : segs) {
            if (seg.first + seg.second > arr->size()) {
                throw std::out_of_range("Segment exceeds array bounds");
            }
            segments.push_back(seg);
        }
    }

    // 按拼接顺序访问第n个元素
    ElementType& operator[](size_t n) {
        size_t total = 0;
        for (auto& seg : segments) {
            if (n < total + seg.second) {
                return (*arr)[seg.first + (n - total)];
            }
            total += seg.second;
        }
        throw std::out_of_range("Index out of view bounds");
    }

    // 获取视图总元素数
    size_t size() const {
        size_t s = 0;
        for (auto& seg : segments) s += seg.second;
        return s;
    }
};

int main() {
    auto arr = std::make_shared<std::vector<float>>(100);
    // 创建视图:包含索引2-5(长度4)和70-99(长度30)的区间
    NonContiguousView view(arr, {{2,4}, {70,30}});
    
    // 像访问普通数组一样操作视图
    view[0] = 1.0f; // 对应原数组索引2
    view[3] = 2.0f; // 对应原数组索引5
    view[4] = 3.0f; // 对应原数组索引70
    return 0;
}

3. 核心注意事项

  • 不要尝试让单个shared_ptr绑定多个分散指针,这违背它的设计逻辑,会导致内存管理混乱。
  • 无论用哪种方案,都要确保原数组的生命周期被正确维护,避免出现野指针。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 09:21:25