C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c – 使用std:vector作为低级缓冲区大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
此处的用法Using read() directly into a C++ std:vector相同,但具有重新分配的数量.

输入文件的大小未知,因此当文件大小超过缓冲区大小时,通过加倍大小来重新分配缓冲区.这是我的代码

#include <vector>
#include <fstream>
#include <iostream>

int main()
{
    const size_t initSize = 1;
    std::vector<char> buf(initSizE); // sizes buf to initSize,so &buf[0] below is valid
    std::ifstream ifile("D:\\Pictures\\input.jpg",std::ios_base::in|std::ios_base::binary);
    if (ifilE)
    {
        size_t bufLen = 0;
        for (buf.reserve(1024); !ifile.eof(); buf.reserve(buf.capacity() << 1))
        {
            std::cout << buf.capacity() << std::endl;
            ifile.read(&buf[0] + bufLen,buf.capacity() - bufLen);
            bufLen += ifile.gcount();
        }
        std::ofstream ofile("rebuild.jpg",std::ios_base::out|std::ios_base::binary);
        if (ofilE)
        {
            ofile.write(&buf[0],bufLen);
        }
    }
}

程序按照预期打印矢量容量,并将输出文件写入与输入BUT相同的大小,在偏移initSize之前只输入与输入相同的字节,之后全部为零…

在read()中使用& buf [bufLen]肯定是一个未定义的行为,但& buf [0] bufLen得到了正确的写入,因为连续分配是有保证的,不是吗? (提供了initSize!= 0.注意std :: vector< char> buf(initSizE);将buf的大小调整为initSize.是的,如果initSize == 0,在我的环境中发生朗姆酒致命错误.)我是否会错过什么?这也是UB吗?标准是否说明了std :: vector的这种用法

PS:是的,我知道我们可以先计算文件大小并分配完全相同的缓冲区大小,但在我的项目中,可以预期输入文件几乎总是小于某个SIZE,@R_668_9447@将initSize设置为SIZE并且期望没有开销(比如文件大小计算),并且仅为“异常处理”使用重新分配.是的,我知道我可以用resize()和capacity()替换reserve()和size(),然后用很少的开销来工作(每次调整大小都是零缓冲区),但是我仍然希望摆脱任何redundent操作,只是一种偏执……

更新1:

事实上,我们可以从标准中推断& buf [0] bufLen得到正确的帖子,虑:

std::vector<char> buf(128);
buf.reserve(512);
char* bufPtr0 = &buf[0],*bufPtrOutofRange = &buf[0] + 200;
buf.resize(256); std::cout << "standard guarantees no realLOCATIOn" << std::endl;
char* bufPtr1 = &buf[0],*bufInRange = &buf[200]; 
if (bufPtr0 == bufPtr1)
    std::cout << "so bufPtr0 == bufPtr1" << std::endl;
std::cout << "and 200 < buf.size(),standard guarantees bufInRange == bufPtr1 + 200" << std::endl;
if (bufInRange == bufPtrOutofRangE)
    std::cout << "finally we have: bufInRange == bufPtrOutofRange" << std::endl;

输出

standard guarantees no realLOCATIOn
so bufPtr0 == bufPtr1
and 200 < buf.size(),standard guarantees bufInRange == bufPtr1 + 200
finally we have: bufInRange == bufPtrOutofRange

并且这里可以用每个buf.size()< = i<来替换200. buf.capacity()和类似的扣除成立. 更新2: 是的,我确实错过了一些东西……但问题不在于连续性(参见更新1),甚至没有写入内存失败.今天我有时间研究这个问题,程序得到正确的地址,将正确的数据写入保留的内存,但是在下一个reserve()中,buf被重新分配,并且只包含范围[0,buf.size中的元素())复制到新内存.所以这就是整个谜语的答案…… 最后注意事项:如果在缓冲区填充了一些数据后不需要重新分配,则绝对可以使用reserve()/ capatity()而不是resize()/ size(),但如果需要,请使用后者. 例:

const size_t initSize = 32;
std::vector<char> buf(initSizE);
buf.reserve(1024*100); // reserve enough space for file reading
std::ifstream ifile("D:\\Pictures\\input.jpg",std::ios_base::in|std::ios_base::binary);
if (ifilE)
{
    ifile.read(&buf[0],buf.capacity());  // ok. the whole file is read into buf
    std::ofstream ofile("rebuld.jpg",std::ios_base::out|std::ios_base::binary);
    if (ofilE)
    {
        ofile.write(&buf[0],ifile.gcount()); // rebuld.jpg just identical to input.jpg
    }
}
buf.reserve(1024*200); // horror! probably always lose all data in buf after offset initSize

PS:我没有发现任何权威来源(标准,TC PL等)明确同意或不同意我提出的上述建议.但是在这里可用的所有实现(VC,g,ICC)下,上面的例子工作正常.

这是另一个例子,引自’TC PL,4e’第1041页,注意函数的第一行使用reserve()而不是resize():

void fill(istream& in,String& s,int maX)
// use s as target for low-level input (simplified)
{
    s.reserve(maX); // make sure there is enough allocated space
    in.read(&s[0],maX);
    const int n = in.gcount(); // number of characters read
    s.resize(n);
    s.shrink_to_fit();  // discard excess capacity
}

解决方法

reserve实际上并没有向向量添加空间,它只确保在调整大小时不需要重新分配.您应该使用resize,而不是使用reserve,一旦知道实际读取了多少字节,就进行最后的调整.

编辑:保证所做的一切是防止迭代器和指针的失效,因为你将向量的大小增加到capacity().除非它们是size()的一部分,否则不保证保留那些保留字节的内容.

大佬总结

以上是大佬教程为你收集整理的c – 使用std:vector作为低级缓冲区全部内容,希望文章能够帮你解决c – 使用std:vector作为低级缓冲区所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。