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
,这在所有方面都更好。