Jeśli chodzi o zmiany w kodzie w oparciu o to, co już masz, najprostsze jest najprawdopodobniej, aby ustawić Page Setter, przyjmując wektor lub wskaźnik wektora niestałego, oraz swap
go z wektorem zawartym na stronie. Rozmówca będzie pozostawiony gospodarstwa pusty wektor, ale ponieważ problem jest nadmierne kopiowanie, przypuszczalnie rozmówca nie chce zachować dane:
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);
}
};
niektórzy ludzie (na przykład Google C++ Podręcznik stylu) chcą parametry referencyjne być const, i chciałby, aby przekazać parametr newcontent
jako wskaźnik, aby podkreślić, że jest non-const:
void setContent(std::vector<char> *newcontent) {
content.swap(*newcontent);
}
swap
jest szybka - można się spodziewać, że po prostu wymienić bufor wskaźniki i rozmiary dwóch obiektów wektorowych.
Alternatywnie, podaj stronę dwa różne konstruktory: jeden dla pliku zip i drugi dla zwykłego pliku oraz czy odpowiada za odczyt własnych danych. Jest to prawdopodobnie najczystsze i pozwala Strona być niezmienna, a nie modyfikowana po zakończeniu budowy. W rzeczywistości możesz tego nie chcieć, ponieważ, jak zauważyłeś w komentarzu, dodanie strony do kontenera powoduje skopiowanie strony. Istnieje więc pewna korzyść z możliwości modyfikowania strony, aby dodać dane, które zostały tanio zbudowane w kontenerze: unika tej dodatkowej kopii bez potrzeby bałagania w pojemnikach ze wskaźnikami. Mimo to funkcja setContent
może równie łatwo wziąć informacje o strumieniu pliku/pliku zip, co zrobić wektor.
Można znaleźć lub napisać klasę strumienia, która czyta z pliku zip, aby strona mogła być odpowiedzialna za odczyt danych za pomocą tylko jednego konstruktora pobierającego strumień. A może nie cała klasa strumieniowa, może tylko interfejs, który projektujesz, który odczytuje dane ze strumienia/zip/rar do określonego bufora, a Strona może określać swój wewnętrzny wektor jako bufor.
W końcu możesz "zadzieżyć z pojemnikami ze wskaźnikami". Dokonaj pages
się std::vector<boost::shared_ptr<Page> >
, a następnie wykonaj:
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
ma skromną napowietrznych względem tylko strony (to sprawia dodatkową alokację pamięci dla małego węzła zawierającego wskaźnik i RefCount), ale jest znacznie tańsze do skopiowania. Jest również w TR1, jeśli masz implementację tego innego niż Boost.
No dobra, nie myślałem o używaniu zamiany. Myślałem o tym, czy strona zajmie się odczytem danych. Rzecz w tym, że ciągle otwierałem plik zip, przeskakując do i czytając 1 obraz i zamykając go. Co gorsza biblioteka unrar nie obsługuje przeskakiwania do elementów. – Kache
"Ciągle otwierałem plik zip, przeskakując do i czytając 1 obraz i zamykając go" - niekoniecznie. Przypuszczalnie twoja klasa "Book" obecnie przechodzi przez zip/rar czytając jeden plik na raz. Konstruktor 'Strona' może mieć takie samo zachowanie, że" pochłania "niektóre dane z obiektu przekazanego do niego. Po prostu bądź ostrożny w obsłudze błędów - ponieważ przeczytałeś niektóre dane i prawdopodobnie nie ma możliwości przywrócenia położenia strumienia do miejsca, w którym zostało rozpoczęte (jeśli nie możesz przeskoczyć do pliku, nie możesz szukać), możesz tylko zaoferować słaba gwarancja wyjątku. –