Skip to content

Latest commit

 

History

History
163 lines (128 loc) · 4.79 KB

File metadata and controls

163 lines (128 loc) · 4.79 KB

Efficiency


Raw pointer

#include <memory>
#include <vector>

struct Data {
    char tab_[42];
};

int main(void) {
    constexpr unsigned size = 10u * 1000u * 1000u;
    std::vector<Data *> v;
    v.reserve(size);
    for (unsigned i = 0; i < size; ++i) {
        auto p = new Data;
        v.push_back(std::move(p));
    }
    for (auto p: v)
        delete p;
}

Unique pointer

#include <memory>
#include <vector>

struct Data {
    char tab_[42];
};

int main(void) {
    constexpr unsigned size = 10u * 1000u * 1000u;
    std::vector<std::unique_ptr<Data>> v;
    v.reserve(size);
    for (unsigned i = 0; i < size; ++i) {
        std::unique_ptr<Data> p{new Data};
        v.push_back(std::move(p));
    }
}

Shared pointer

#include <memory>
#include <vector>

struct Data {
    char tab_[42];
};

int main(void) {
    constexpr unsigned size = 10u * 1000u * 1000u;
    std::vector<std::shared_ptr<Data>> v;
    v.reserve(size);
    for (unsigned i = 0; i < size; ++i) {
        std::shared_ptr<Data> p{new Data};
        v.push_back(std::move(p));
    }
}

Shared pointer – make_shared

#include <memory>
#include <vector>

struct Data {
    char tab_[42];
};

int main(void) {
    constexpr unsigned size = 10u * 1000u * 1000u;
    std::vector<std::shared_ptr<Data>> v;
    v.reserve(size);
    for (unsigned i = 0; i < size; ++i) {
        auto p = std::make_shared<Data>();
        v.push_back(std::move(p));
    }
}

Weak pointer

#include <memory>
#include <vector>

struct Data {
    char tab_[42];
};

int main(void) {
    constexpr unsigned size = 10u * 1000u * 1000u;
    std::vector<std::shared_ptr<Data>> vs;
    std::vector<std::weak_ptr<Data>> vw;
    vs.reserve(size);
    vw.reserve(size);
    for (unsigned i = 0; i < size; ++i) {
        std::shared_ptr<Data> p{new Data};
        std::weak_ptr<Data> w{p};
        vs.push_back(std::move(p));
        vw.push_back(std::move(w));
    }
}

Measurements

  • gcc-4.8.2
  • compilation with –std=c++11 –O3 –DNDEBUG
  • measuring with:
    • time (real)
    • htop (mem)
    • valgrind (allocations count)

Results

test name time [s] allocations memory [MB]
raw pointer 0.54 10 000 001 686
unique pointer 0.56 10 000 001 686
shared pointer 1.00 20 000 001 1072
make shared 0.76 10 000 001 914
weak pointer 1.28 20 000 002 1222

Conclusions

  • RAII
    • acquire resource in constructor
    • release resource in destructor
  • Rule of 5, Rule of 0
  • Smart pointers:
    • std::unique_ptr – primary choice, no overhead, can convert to std::shared_ptr
    • std::shared_ptr – introduces memory and runtime overhead
    • std::weak_ptr – breaking cycles, can convert to/from std::shared_ptr
  • Create smart pointers with std::make_shared() and std::make_unique()
  • Raw pointer should mean „access only” (no ownership)
  • Use reference instead of pointers if possible