我正在测试istream中各种数据读取技术的速度,因此我创建了一个从文件重复创建istream的功能,因此,所测试的下一个方法可以使用该istream。
using std::istream;
using std::string;
istream* getStreamFrom(string filepath)
{
std::filebuf init_buffer;
if (init_buffer.open(filepath, std::ios::in))
{
std::istream inputStream(&init_buffer);
init_buffer.close();
return &inputStream;
}
// file not found
istream inputStream(0);
return &inputStream;
}
然后,我将istream传递给经过测试的方法,如下所示:
istream* data = getStreamFrom(FILEPATH);
someMethod(*data);
但是在someMethod
中,从istream读取时出现访问冲突:
void someMethod(istream& input)
{
string line;
while (std::getline(input, line)) // code failes here
// do something
}
为什么会这样,我该如何解决?无论是否找到文件都无所谓,在两种情况下都会发生。
inputStream
将进入我们的范围。在函数外部访问std::istream*
将导致不确定的行为。
可能最好的方法是使用std::shared_ptr
。像这样的东西:
std::shared_ptr<std::istream> getStreamFrom(string filepath)
{
std::filebuf init_buffer;
if (init_buffer.open(filepath, std::ios::in))
{
std::shared_ptr<std::istream> inputStream = std::make_shared<std::istream>(&init_buffer);
init_buffer.close();
return inputStream;
}
// file not found
std::shared_ptr<std::istream> inputStream = std::make_shared<istream>(nullptr);
return inputStream;
}
当然,init_buffer
也将超出范围。不确定passing it directly into std::istream
won't delete the buffer是什么正确的方法。我不知道正确的方法是在这里,因为您没有制作自己的std::istream
,因此建议的解决方案对您不起作用。因此,您对此感到有点自己。但是你已经被警告过。
您可以做的一件事是std::istream
它。这是一些std::move()
。
如果要从函数返回本地流,则需要同时动态分配流及其缓冲区。正如注释和答案所解释的那样,您正在返回指向局部变量的指针,该局部变量将在函数退出后销毁。标准流类std::move()
和more information on std::move()
ing things是不可移动的,因此您唯一的选择是在堆上创建对象。流和缓冲区都可以包装在智能指针中,以避免手动管理内存。
std::move()
顺便说一下,用std::istream
初始化的std::ostream
是std::unique_ptr<std::istream> getStreamFrom(std::string filepath) {
auto init_buf = std::make_unique<std::filebuf>();
return std::make_unique<std::istream>(
init_buf->open(filepath, std::ios_base::in)
? init_buf.release()->close()
: nullptr
);
}
。您也可以返回指向它的指针:
std::istream
[在C ++ 17中为可选:
std::filebuf