Optimizing sorting container of objects with heap-allocated buffers - how to avoid hard-copying buff

Posted by Kache4 on Stack Overflow See other posts from Stack Overflow or by Kache4
Published on 2010-03-15T16:21:34Z Indexed on 2010/03/15 17:29 UTC
Read the original article Hit count: 260

Filed under:
|
|

I was making sure I knew how to do the op= and copy constructor correctly in order to sort() properly, so I wrote up a test case. After getting it to work, I realized that the op= was hard-copying all the data_.

I figure if I wanted to sort a container with this structure (its elements have heap allocated char buffer arrays), it'd be faster to just swap the pointers around. Is there a way to do that? Would I have to write my own sort/swap function?

#include    <deque>
//#include  <string>
//#include  <utility>
//#include  <cstdlib>
#include    <cstring>
#include    <iostream>
//#include  <algorithm> // I use sort(), so why does this still compile when commented out?

#include    <boost/filesystem.hpp>
#include    <boost/foreach.hpp>

using namespace std;

namespace fs = boost::filesystem;

class Page
{
    public:
        // constructor
        Page(const char* path, const char* data, int size) :
            path_(fs::path(path)),
            size_(size),
            data_(new char[size])
        {
//          cout    << "Creating Page..." << endl;
            strncpy(data_, data, size);
//          cout    << "done creating Page..." << endl;
        }
        // copy constructor
        Page(const Page& other) :
            path_(fs::path(other.path())),
            size_(other.size()),
            data_(new char[other.size()])
        {
//          cout    << "Copying Page..." << endl;
            strncpy(data_, other.data(), size_);
//          cout    << "done copying Page..." << endl;
        }
        // destructor
        ~Page() { delete[] data_; }
        // accessors
        const fs::path& path() const { return path_; }
        const char* data() const { return data_; }
        int size() const { return size_; }
        // operators
        Page& operator = (const Page& other) {
            if (this == &other)
                return *this;
            char* newImage = new char[other.size()];
            strncpy(newImage, other.data(), other.size());
            delete[] data_;
            data_ = newImage;
            path_ = fs::path(other.path());
            size_ = other.size();
            return *this;
        }
        bool operator < (const Page& other) const { return path_ < other.path();    }
    private:
        fs::path path_;
        int size_;
        char* data_;
};

class Book
{
    public:
        Book(const char* path) :
            path_(fs::path(path))
        {
            cout    << "Creating Book..." << endl;
            cout    << "pushing back #1" << endl;
            pages_.push_back(Page("image1.jpg", "firstImageData", 14));
            cout    << "pushing back #3" << endl;
            pages_.push_back(Page("image3.jpg", "thirdImageData", 14));
            cout    << "pushing back #2" << endl;
            pages_.push_back(Page("image2.jpg", "secondImageData", 15));

            cout    << "testing operator <" << endl;
            cout    << pages_[0].path().string() << (pages_[0] < pages_[1]? " < " : " > ") << pages_[1].path().string() << endl;
            cout    << pages_[1].path().string() << (pages_[1] < pages_[2]? " < " : " > ") << pages_[2].path().string() << endl;
            cout    << pages_[0].path().string() << (pages_[0] < pages_[2]? " < " : " > ") << pages_[2].path().string() << endl;

            cout    << "sorting" << endl;
            BOOST_FOREACH (Page p, pages_)
                cout    << p.path().string() << endl;
            sort(pages_.begin(), pages_.end());
            cout << "done sorting\n";
            BOOST_FOREACH (Page p, pages_)
                cout    << p.path().string() << endl;

            cout    << "checking datas" << endl;
            BOOST_FOREACH (Page p, pages_) {
                char data[p.size() + 1];
                strncpy((char*)&data, p.data(), p.size());
                data[p.size()] = '\0';
                cout    << p.path().string() << " " << data << endl;
            }
            cout    << "done Creating Book" << endl;
        }
    private:
        deque<Page> pages_;
        fs::path path_;
};

int main() {
    Book* book = new Book("/some/path/");
}

© Stack Overflow or respective owner

Related posts about c++

Related posts about sort