使用C ++和RAII读取文件

时间:2014-06-02 07:27:43

标签: c++ raii

使用C ++和RAII读取文件的最佳方法是什么?我见过的所有例子都使用了与下面代码类似的东西:

#include <iostream>
#include <fstream>

int main () {

  std::ifstream is ("test.txt", std::ifstream::binary);
  if (is) {
    is.seekg (0, is.end);
    int length = is.tellg();
    is.seekg (0, is.beg);

    char * buffer = new char [length]; // Seems wrong?

    is.read (buffer, length);

    delete[] buffer;
  }
}

根据我对RAII的了解,初始化一个字符指针并手动删除它似乎是错误的。

我做过类似的事情:

#include <iostream>
#include <fstream>

int main () {

  std::ifstream is ("test.txt", std::ifstream::binary);
  if (is) {
    is.seekg (0, is.end);
    int length = is.tellg();
    is.seekg (0, is.beg);

    std::shared_ptr<char> buffer = std::make_shared<char>();

    is.read (buffer.get(), length);
  }
}

但我不确定这是否也是正确的。如果需要,我也无法成功std::shared_ptr<char>投放std::shared_ptr<uint8_t>(或者如果可能,或者甚至有意义?)。

2 个答案:

答案 0 :(得分:4)

  

char * buffer = new char [length]; //似乎错了?

没错,只是......不安全。

更安全的实施:

std::unique_ptr<char[]> buffer{new char [length]}; // note: use char[] as parameter
is.read (buffer.get(), length);

比以前更好:

std::vector<char> buffer{length, ' '};
is.read (buffer.data(), length);

或:

std::string buffer{length, ' '};
is.read (buffer.data(), length);

特别是,这是UB:

std::shared_ptr<char> buffer = std::make_shared<char>();
is.read (buffer, length);

因为它动态分配一个字符,然后在该内存位置放置长度字符。实际上,这是缓冲区溢出,除非您的长度始终为1。

答案 1 :(得分:0)

std :: shared_ptr(和其他智能指针一样)将RAII应用于对象的单个实例(这里是一个char,oops!)

您正在寻找std :: vector,您可以通过调用vec.reserve()来预先分配。

关于将它转换为uint8_t,我说一旦你读完你的数据并将结果转换为uint8_t就调用vec.data()应该按预期工作(我不肯断它是标准的虽然)。