考虑一个包含class Page的stl容器的class Book。每个Page包含一个屏幕截图,就像原始vector<char>表单中的page10.jpg一样。
打开一个Book,其中包含一个zip、rar或包含这些屏幕截图的目录的路径,并使用各自的方法来提取原始数据,如ifstream inFile.read(buffer, size);或unzReadCurrentFile(zipFile, buffer, size)。然后,它调用Page(const char* stream, int filesize)构造函数。
现在,很明显原始数据被复制了两次。一次提取到图书的本地buffer,第二次在Page ctor中提取到Page::vector<char>。有没有一种方法可以在消除中间人缓冲区的同时保持封装?
发布于 2010-03-25 09:23:54
根据已有的代码更改,最简单的方法可能是为Page提供一个setter方法,该方法采用非常量向量引用或指针,并使用Page中包含的向量对其进行swap。调用者将保留一个空向量,但由于问题是过度复制,因此调用者可能不想保留数据:
void Book::addPage(ifstream file, streampos size) {
std::vector<char> vec(size);
file.read(&vec[0], size);
pages.push_back(Page()); // pages is a data member
pages.back().setContent(vec);
}
class Page {
std::vector<char> content;
public:
Page() : content(0) {} // create an empty page
void setContent(std::vector<char> &newcontent) {
content.swap(newcontent);
}
};有些人(例如谷歌C++风格指南)希望引用参数为常量,并希望您将newcontent参数作为指针传递,以强调它是非常量:
void setContent(std::vector<char> *newcontent) {
content.swap(*newcontent);
}swap速度很快--你会期望它只交换两个矢量对象的缓冲区指针和大小。
或者,为Page提供两个不同的构造函数:一个用于zip文件,另一个用于常规文件,并让它负责读取自己的数据。这可能是最干净的,而且它允许Page是不可变的,而不是在构造之后被修改。但实际上您可能不希望这样,因为正如您在注释中注意到的那样,将Page添加到容器中会复制Page。因此,在容器中以较低的成本构造数据之后,能够修改页面以添加数据有一些好处:它避免了额外的复制,而不需要处理指针容器。尽管如此,setContent函数可以像获取向量一样轻松地获取文件流/压缩文件信息。
您可以找到或编写一个从zipfile读取数据的流类,这样Page就可以只使用一个获取流的构造函数来负责读取数据。或者可能不是整个流类,也许只是您设计的一个接口,它将数据从stream/zip/rar读取到指定的缓冲区中,Page可以将其内部向量指定为缓冲区。
最后,你可以“搞乱指针的容器”。将pages设置为std::vector<boost::shared_ptr<Page> >,然后执行以下操作:
void Book::addPage(ifstream file, streampos size) {
boost::shared_ptr<Page> page(new Page(file, size));
pages.push_back(page); // pages is a data member
}与页面相比,shared_ptr具有适度的开销(它为包含指针和引用计数的小节点分配了额外的内存),但复制成本要低得多。它也是用TR1编写的,如果你有Boost之外的其他实现。
发布于 2010-03-25 08:23:23
最初使用std::vector resize成员设置缓冲区大小,然后通过front()的地址直接使用其缓冲区。
std::vector<char> v;
v.resize(size);
strcpy(&v.front(), "testing");&v.front()提供了对std::vector的直接缓冲区访问
发布于 2010-03-25 09:07:48
使用std::vector保存图像数据不是一个好主意。为此,我将使用原始指针或shared_ptr。这可以防止缓冲区被复制两次。
因为你关心内存,所以在内存中保存所有的图像数据对我来说也不是一个好主意。一种更好的方法是将其封装到单独的类中。例如,ImageData。该类包含图像数据的行指针。首先可以使用文件路径初始化该类,然后在需要时从磁盘加载图像数据。
https://stackoverflow.com/questions/2512371
复制相似问题