C++ 制作C++;指向已分配内存的向量

C++ 制作C++;指向已分配内存的向量,c++,multidimensional-array,stdvector,large-files,C++,Multidimensional Array,Stdvector,Large Files,我正在使用一些较旧的代码,将一块RAM装入一个二进制文件。二进制文件是一系列8位灰度图像平面,X X X Y,Z平面深。这些文件通常在500兆到10千兆字节之间 现有代码使用复杂的指针排列来访问XY、XZ或YZ平面中的各个平面 我想做的是用单个向量替换指针,其中每个子向量都是数据中的XY平面。这样做的目的是获得一些安全性,并检查向量,而不是原始指针访问 基于上一个问题()我有以下代码 //preallocate.h template <typename T> class PreAll

我正在使用一些较旧的代码,将一块RAM装入一个二进制文件。二进制文件是一系列8位灰度图像平面,X X X Y,Z平面深。这些文件通常在500兆到10千兆字节之间

现有代码使用复杂的指针排列来访问XY、XZ或YZ平面中的各个平面

我想做的是用单个向量替换指针,其中每个子向量都是数据中的XY平面。这样做的目的是获得一些安全性,并检查向量,而不是原始指针访问

基于上一个问题()我有以下代码

//preallocate.h
template <typename T>
class PreAllocator
{
private:
T* memory_ptr;
std::size_t memory_size;

public:
typedef std::size_t     size_type;
typedef T*              pointer;
typedef T               value_type;

PreAllocator(T* memory_ptr, std::size_t memory_size) : memory_ptr(memory_ptr), memory_size(memory_size) {}

PreAllocator(const PreAllocator& other) throw() : memory_ptr(other.memory_ptr), memory_size(other.memory_size) {};

template<typename U>
PreAllocator(const PreAllocator<U>& other) throw() : memory_ptr(other.memory_ptr), memory_size(other.memory_size) {};

template<typename U>
PreAllocator& operator = (const PreAllocator<U>& other) { return *this; }
PreAllocator<T>& operator = (const PreAllocator& other) { return *this; }
~PreAllocator() {}


pointer allocate(size_type n, const void* hint = 0) {return memory_ptr;}
void deallocate(T* ptr, size_type n) {}

size_type max_size() const {return memory_size;}
};
//preallocate.h
模板
类预分配器
{
私人:
T*存储器_ptr;
std::大小\u t内存大小;
公众:
typedef std::size\u t size\u type;
typedef T*指针;
类型定义T值_类型;
预分配器(T*memory_ptr,std::size_T memory_size):memory_ptr(memory_ptr),memory_size(memory_size){
PreAllocator(const-PreAllocator&other)throw():memory_ptr(other.memory_ptr),memory_size(other.memory_size){};
模板
PreAllocator(const-PreAllocator&other)throw():memory_ptr(other.memory_ptr),memory_size(other.memory_size){};
模板
PreAllocator&operator=(const PreAllocator&other){return*this;}
PreAllocator&operator=(const PreAllocator&other){return*this;}
~PreAllocator(){}
指针分配(大小\u类型n,常量void*hint=0){返回内存\u ptr;}
无效解除分配(T*ptr,大小_类型n){}
size\u type max\u size()常量{返回内存大小;}
};
简化的主要功能如下所示:

TOMhead header;
uint8_t* TOMvolume;
size_t volumeBytes = 0;

int main(int argc, char *argv[])
{
    std::fstream TOMfile;
    std::ios_base::iostate exceptionMask = TOMfile.exceptions() | std::ios::failbit| std::ifstream::badbit;
    TOMfile.exceptions(exceptionMask);

    try {
        TOMfile.open(argv[1],std::ios::in|std::ios::binary);
    }
    catch (std::system_error& error) {
        std::cerr << error.code().message() << std::endl;
        return ERROR;
    }

    TOMfile.read((char*) &header, sizeof(header));
    if (!TOMfile)
    {
        std::cout<<"Error reading file into memory, expected to read " << sizeof(header) << " but only read " << TOMfile.gcount() << "bytes" <<std::endl;
        return ERROR;
    }


    TOMfile.seekg(std::ios_base::beg);      // rewind to begining of the file
    TOMfile.seekg(sizeof(header));          // seek to data beyond the header

    volumeBytes = (header.xsize * header.ysize * header.zsize);

    std::cout << "Trying to malloc " << volumeBytes << " bytes of RAM" << std::endl;

    TOMvolume = (uint8_t*) malloc(volumeBytes);
    if (TOMvolume == NULL)
    {
        std::cout << "Error allocating RAM for the data" << std::endl;
        return ERROR;
    }
TOMfile.read((char*) TOMvolume,volumeBytes);
TOMhead报头;
uint8_t*TOMvolume;
大小\u t体积字节=0;
int main(int argc,char*argv[])
{
std::fstream TOMfile;
std::ios_base::iostate exceptionMask=TOMfile.exceptions()| std::ios::failbit | std::ifstream::badbit;
异常(异常任务);
试一试{
open(argv[1],std::ios::in | std::ios::binary);
}
捕获(标准::系统错误和错误){

std::cerr不可能将内存分配给向量,同时保留内存的先前内容

工作方法:

  • 根本不要使用malloc
  • 使用默认分配器创建一个具有必要大小的向量
  • 将二进制文件直接加载到向量中

在一个假设的情况下,由于分配部分位于库中的某个深处,因此无法触及分配部分:不要使用向量。您已经有了一个动态数组。基于迭代器的算法与指针配合得很好。对于基于范围的算法,您需要类似于
std::span
(C++20)或类似的内容

但使用向量进行分配会更安全,因此更好


如果您的文件高达10 GB,那么我建议您尝试对文件进行内存映射。映射的内存也不能用作向量的存储,因此应该采取不使用向量的方法。不幸的是,没有标准的方法来对文件进行内存映射。

我觉得您似乎在尝试使用此分配器方案o读取预先分配的内存。它只是重复使用已分配的内存,而不是读取它。每次
推回(volumeBytes)
您将用
volumeBytes
的任何值覆盖映射内存的1个字节。如果您的目标是在
TOMvalue
中读取内存,那么这种方法将不起作用。与其
malloc
ing内存,然后尝试将其映射到
std::vector
为什么不创建一个大小合适的
std::vector
并直接读取?或者使用Boost.MultiArray的
Boost::multi_array_ref
(无论您是真的想要多维数组还是只需要一维切片)@aschepler我正在考虑转移到boost,但当我最后一次查看时,没有明显的方法可以将文件直接读取到多数组中,这与标准向量不同。@FrançoisAndrieux我的目标是让一块已经填充的内存看起来像向量,并且可以被向量访问。我尝试了几种方法,但无法让向量实现它已经指向分配的数据,因此它认为它的大小为零。谢谢。我认为内存映射文件将是最终的结果,尤其是随着较新的数据文件趋向于更大的大小。我需要研究它的兼容性-理想情况下,我需要针对windows和macos。
std::vector<uint8_t, PreAllocator<uint8_t>> v_TOMvolume(0, PreAllocator<uint8_t>(&TOMvolume[0], volumeBytes));
v_TOMvolume.push_back(volumeBytes);