raw, weak_ptr, unique_ptr, shared_ptr etc… How to choose them wisely?

There is a lot of pointers in C++ but to be honest in 5 years or so in C++ programming (specifically with the Qt Framework) I only use the old raw pointer:

SomeKindOfObject *someKindOfObject = new SomeKindOfObject();

I know there are a lot of other “smart” pointers:

// shared pointer:
shared_ptr<SomeKindofObject> Object;

// unique pointer:
unique_ptr<SomeKindofObject> Object;

// weak pointer:
weak_ptr<SomeKindofObject> Object;

But I don’t have the slightest idea of what to do with them and what they can offer me in comparison of raw pointers.

For example I have this class header:

#ifndef LIBRARY
#define LIBRARY

class LIBRARY
{
public:
    // Permanent list that will be updated from time to time where
    // each items can be modified everywhere in the code:
    QList<ItemThatWillBeUsedEveryWhere*> listOfUselessThings; 
private:
    // Temporary reader that will read something to put in the list
    // and be quickly deleted:
    QSettings *_reader;
    // A dialog that will show something (just for the sake of example):
    QDialog *_dialog;
};

#endif 

This is clearly not exhaustive but for each of these 3 pointers is it OK to leave them “raw” or should I use something more appropriate?

And in the second time, if an employer will read the code, will he be strict on what kind of pointers I use or not?

2

A “raw” pointer is unmanaged. That is, the following line:

SomeKindOfObject *someKindOfObject = new SomeKindOfObject();

… will leak memory if an accompanying delete is not executed at the proper time.

auto_ptr

In order to minimize these cases, std::auto_ptr<> was introduced. Due to the limitations of C++ prior to the 2011 standard, however, it’s still very easy for auto_ptr to leak memory. It is sufficient for limited cases, such as this, however:

void func() {
    std::auto_ptr<SomeKindOfObject> sKOO_ptr(new SomeKindOfObject());
    // do some work
    // will not leak if you do not copy sKOO_ptr.
}

One of its weakest use-cases is in containers. This is because if a copy of an auto_ptr<> is made and the old copy is not carefully reset, then the container may delete the pointer and lose data.

unique_ptr

As a replacement, C++11 introduced std::unique_ptr<>:

void func2() {
    std::unique_ptr<SomeKindofObject> sKOO_unique(new SomeKindOfObject());

    func3(sKOO_unique); // now func3() owns the pointer and sKOO_unique is no longer valid
}

Such a unique_ptr<> will be correctly cleaned up, even when it’s passed between functions. It does this by semantically representing “ownership” of the pointer – the “owner” cleans it up. This makes it ideal for use in containers:

std::vector<std::unique_ptr<SomeKindofObject>> sKOO_vector();

Unlike auto_ptr<>, unique_ptr<> is well-behaved here, and when the vector resizes, none of the objects will be accidentally deleted while the vector copies its backing store.

shared_ptr and weak_ptr

unique_ptr<> is useful, to be sure, but there are cases where you want two parts of your code base to be able to refer to the same object and copy the pointer around, while still being guaranteed proper cleanup. For example, a tree might look like this, when using std::shared_ptr<>:

template<class T>
struct Node {
    T value;
    std::shared_ptr<Node<T>> left;
    std::shared_ptr<Node<T>> right;
};

In this case, we can even hold on to multiple copies of a root node, and the tree will be properly cleaned up when all copies of the root node are destroyed.

This works because each shared_ptr<> holds on to not only the pointer to the object, but also a reference count of all of the shared_ptr<> objects that refer to the same pointer. When a new one is created, the count goes up. When one is destroyed, the count goes down. When the count reaches zero, the pointer is deleted.

So this introduces a problem: Double-linked structures end up with circular references. Say we want to add a parent pointer to our tree Node:

template<class T>
struct Node {
    T value;
    std::shared_ptr<Node<T>> parent;
    std::shared_ptr<Node<T>> left;
    std::shared_ptr<Node<T>> right;
};

Now, if we remove a Node, there’s a cyclic reference to it. It’ll never be deleted because its reference count will never be zero.

To solve this problem, you use a std::weak_ptr<>:

template<class T>
struct Node {
    T value;
    std::weak_ptr<Node<T>> parent;
    std::shared_ptr<Node<T>> left;
    std::shared_ptr<Node<T>> right;
};

Now, things will work correctly, and removing a node will not leave stuck references to the parent node. It makes walking the tree a little more complicated, however:

std::shared_ptr<Node<T>> parent_of_this = node->parent.lock();

This way, you can lock a reference to the node, and you have a reasonable guarantee it won’t disappear while you’re working on it, since you’re holding on to a shared_ptr<> of it.

make_shared and make_unique

Now, there are some minor problems with shared_ptr<> and unique_ptr<> that should be addressed. The following two lines have a problem:

foo_unique(std::unique_ptr<SomeKindofObject>(new SomeKindOfObject()), thrower());
foo_shared(std::shared_ptr<SomeKindofObject>(new SomeKindOfObject()), thrower());

If thrower() throws an exception, both lines will leak memory. And more than that, shared_ptr<> holds the reference count far away from the object it points to and this can mean a second allocation). That’s not usually desirable.

C++11 provides std::make_shared<>() and C++14 provides std::make_unique<>() to solve this problem:

foo_unique(std::make_unique<SomeKindofObject>(), thrower());
foo_shared(std::make_shared<SomeKindofObject>(), thrower());

Now, in both cases, even if thrower() throws an exception, there will not be a leak of memory. As a bonus, make_shared<>() has the opportunity to create its reference count in the same memory space as its managed object, which can both be faster and can save a few bytes of memory, while giving you an exception safety guarantee!

Notes about Qt

It should be noted, however, that Qt, which must support pre-C++11 compilers, has its own garbage-collection model: Many QObjects have a mechanism where they will be destroyed properly without the need for the user to delete them.

I do not know how QObjects will behave when managed by C++11 managed pointers, so I can not say that shared_ptr<QDialog> is a good idea. I do not have enough experience with Qt to say for sure, but I believe that Qt5 has been adjusted for this use case.

10

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật