C++ 让一个'std::vector<;无符号字符>;`从'std::string'中窃取内存`
假设我们有C++ 让一个'std::vector<;无符号字符>;`从'std::string'中窃取内存`,c++,stdvector,move-semantics,stringstream,rvalue-reference,C++,Stdvector,Move Semantics,Stringstream,Rvalue Reference,假设我们有std::string s保存原始数据缓冲区,但我们想要std::vector v。缓冲区长度以百万为单位。有没有一种简单的方法可以让v窃取s的内存,从而避免复制缓冲区 就像std::vector::vector(std::string&&)应该做的那样,但是从STL的外部进行 或者,是否可以从std::stringstream ss获取v,其操作效率与ss.str()差不多?好的,这里有很多评论,让我们试着把一些东西放在一起,因为我需要练习,可能会获得一些分数[update:Have
std::string s
保存原始数据缓冲区,但我们想要std::vector v
。缓冲区长度以百万为单位。有没有一种简单的方法可以让v
窃取s
的内存,从而避免复制缓冲区
就像std::vector::vector(std::string&&)
应该做的那样,但是从STL的外部进行
或者,是否可以从
std::stringstream ss
获取v
,其操作效率与ss.str()
差不多?好的,这里有很多评论,让我们试着把一些东西放在一起,因为我需要练习,可能会获得一些分数[update:Haven't:(]
我对“现代C++”还比较陌生,所以请你随便看看。可能最晚需要C++17,我还没有仔细检查。任何批评都非常欢迎,但我更愿意编辑我自己的帖子。阅读本文时请记住,OP实际上想做的是从文件.Thx中读取他的字节
更新:根据@Deduplicator下面的评论,调整以处理在调用stat()
和调用fread()
之间文件大小发生变化的情况……然后将fread
替换为std::ifstream
,我想我们现在就到了
#include <string>
#include <vector>
#include <optional>
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
using optional_vector_of_char = std::optional <std::vector <char>>;
// Read file into a std::optional <std::vector <char>>.
// Now handles the file size changing when we're not looking.
optional_vector_of_char SmarterReadFileIntoVector (std::string filename)
{
for ( ; ; )
{
struct stat stat_buf;
int err = stat (filename.c_str (), &stat_buf);
if (err)
{
// handle the error
return optional_vector_of_char (); // or maybe throw an exception
}
size_t filesize = stat_buf.st_size;
std::ifstream fs;
fs.open (filename, std::ios_base::in | std::ios_base::binary);
if (!fs.is_open ())
{
// handle the error
return optional_vector_of_char ();
}
optional_vector_of_char v (filesize + 1);
std::vector <char>& vecref = v.value ();
fs.read (vecref.data (), filesize + 1);
if (fs.rdstate () & std::ifstream::failbit)
{
// handle the error
return optional_vector_of_char ();
}
size_t bytes_read = fs.gcount ();
if (bytes_read <= filesize) // file same size or shrunk, this code handles both
{
vecref.resize (bytes_read);
vecref.shrink_to_fit ();
return v; // RVO
}
// File has grown, go round again
}
}
int main ()
{
optional_vector_of_char v = SmarterReadFileIntoVector ("abcde");
std::cout << std::boolalpha << v.has_value () << std::endl;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用可选的\u向量\u of_char=std::optional;
//将文件读入std::可选。
//现在,我们可以在不查看时处理文件大小的更改。
可选的\u向量\u的\u char SmarterReadFileIntoVector(std::string文件名)
{
对于(;;)
{
结构统计;
int err=stat(filename.c_str(),&stat_buf);
如果(错误)
{
//处理错误
返回可选的_vector _of _char();//或者抛出异常
}
size\u t filesize=stat\u buf.st\u size;
std::iffs流;
fs.open(文件名,std::ios_base::in | std::ios_base::binary);
如果(!fs.is_open())
{
//处理错误
返回_char()的可选_向量_;
}
可选的字符v的字符向量(文件大小+1);
std::vector&vecref=v.value();
fs.read(vecref.data(),filesize+1);
if(fs.rdstate()&std::ifstream::failbit)
{
//处理错误
返回_char()的可选_向量_;
}
size_t bytes_read=fs.gcount();
如果(字节读取如果向量和字符串都有一个自定义分配器,那么您可能可以这样做为什么不首先使用向量作为缓冲区?@Museful为什么不使用fread
?哦,那么这很简单-获取文件的长度-请看,分配一个合适大小的向量并读入其中。但是我认为您是obse对所谓的“意图”的理解太多了。字符串和字节向量实际上是等价的。std::strings处理“二进制”数据很好。有一个明显的TOCTOU错误,因为文件在stat和open之间可能会改变长度。另外,你为什么不想在非Windows上读取二进制文件,因为根据你的评论,这似乎是正确的事情?@Deduplicator的确,我很傻,尽管听起来它不适用于OP。我已经相应地修改了代码。如对于第2点,除了Windows以外的平台上的二进制文件和文本文件没有区别,因为不需要翻译行尾。指定“rb”或“rt”)因为mode参数是Windows扩展。b
不是Windows扩展,即使它在Unix上不起任何作用,但在早期的系统中,二进制文件和文本文件是不同的。另请参见@Deduplicator OK,我看到文件访问模式标志“b”可以选择指定为以二进制模式打开文件。此标志对POSIX系统没有影响,但在Windows上它禁用了对“\n”和“\x1A”的特殊处理。我担心一些平台可能会反对“rb”
。无论如何,现在没有必要了,我将代码更改为使用ifstream
,这在所有方面都更好。