Retrieve, then pass the raw data to another class. How to avoid copying while maintaining encapsulation?

Consider a class Bookwith the stl container class Page. each Pagehas a screenshot, for example page10.jpgin the form of raw vector<char>.

A is Bookopened using the path to the zip, rar, or directory containing these screenshots, and uses the appropriate methods to extract raw data, such as ifstream inFile.read(buffer, size);or unzReadCurrentFile(zipFile, buffer, size). Then it calls the constructor Page(const char* stream, int filesize).

It is now clear that the original data is copied twice. Once removed in the local book bufferand a second time in Pagector's Page::vector<char>. Is there a way to support encapsulation by getting rid of the proxy buffer?

+5
source share
5 answers

In terms of code changes based on what you already have, the simplest is probably to provide a Page set seter that accepts a non-constant vector link or pointer, and swapwith the vector contained on the page. The call will contain an empty vector, but since the problem is excessive copying, the caller presumably does not want to save the data:

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);
    }
};

Some people (like the Google C ++ style guide) want the reference parameters to be const, and would like you to pass the parameter newcontentas a pointer to emphasize that it is not const:

void setContent(std::vector<char> *newcontent) {
    content.swap(*newcontent);
}

swap runs fast - you expect it to simply replace the pointers to the buffer and the sizes of two vector objects.

, : zip . , , , Page , . , , , . , , , , : , . , setContent / zip , .

, zip , , . , , , , , , /zip/rar , .

, " ". pages a 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
}

A shared_ptr ( node, refcount), . TR1, , Boost.

+3

std::vector resize, , front().

std::vector<char> v;
v.resize(size);
strcpy(&v.front(), "testing");

std::vector : &v.front()

+2

std::vector - . raw- shared_ptr. .

, . . , ImageData. . , , .

+2

, Page , Book , , ( , Book , , ).

, , , Book . Page, .

, zip , , , . , Minizip, , , Minizip . unzGoToFirstFile() unzGoToNextFile() zip ( , ) unzReadCurrentFile() . Book Minizip . zip Page, zip . Book unzGoToNextFile() , Page. , . :

Page::Page(zipFile file)
{
    //  TODO:  Determine the required size of the buffer that will store the data
    unsigned buffer_size;

    data_.resize(buffer_size)

    unzReadCurrentFile(file, &data_[0], buffer_size);
}

void Book::open(const std::string &filename)
{
    zipFile file = unzOpen(filename.c_str());

    int result = unzGoToFirstFile(file);
    while (result == UNZ_OK)
    {
        pages_.push_back(Page(file));
        unzGoToNextFile(file);
    }
}

( Minizip , ), , Book Page pages_ Page data_.

+1

, . , . , . (, , - ), , , , .

, . . (, ) , .

0

All Articles