Home PC Games Linux Windows Database Network Programming Server Mobile  
           
  Home \ Programming \ Boost - Memory Management - smart pointers     - C ++ implementation of the list of basic operations and test cases (Programming)

- MongoDB in bulk timestamp change the date format (Database)

- Commonly used Linux system camouflage method (Linux)

- Save the database data files into Oracle Learning (Database)

- Python implementation Bursa transition model (Programming)

- Linux supports serial output method (Linux)

- The REVERSE function of DB2 (Database)

- Binary tree to the next node (Programming)

- GNU Linux system variables (sysctl configuration commands) integrated use (Linux)

- Python 3 for instructions encoded string conversion (Programming)

- Configuring s3c-linux-2.6.28.6-Real6410 appears Unable to find the QT3 installation (Linux)

- RHEL5 / 6 Installation Notes (Linux)

- Django1.8 return json json string and the string contents of the received post (Programming)

- Java Access Control (Programming)

- The Oracle VM VirtualBox use U disk under ubuntu (Linux)

- Getting Started with Linux system to learn: how to check in a package is installed on Ubuntu (Linux)

- Oracle local user login authentication fails ORA-01031 insufficient privileges (Database)

- C ++ Supplements - locates the new expression (Programming)

- Linux kernel likely and unlikely to resolve macro definitions (Linux)

- Nginx supports user multi-threaded downloads and resume broken (Server)

 
         
  Boost - Memory Management - smart pointers
     
  Add Date : 2018-11-21      
         
         
         
  (A) RAII mechanism

Mechanism RAII (resource acquisition is initialization, Resource Acquisition Is Initialization), application resources in the constructor use of resources of the class, and then use the last release of resources in the destructor.

If the object is created on the stack it (such as a local object), then RAAII mechanism would work, when the end of the life cycle of an object invokes its destructor to free up resources. But when the object is created on the heap (with the new operator), then the order of the object destructor memory is required to call the delete operator. Dangers This this way, when we forgot to delete after new will cause a memory leak.

(B) the smart pointers

boost.smart_ptr library provides six smart pointers, including: scoped_ptr, scoped_array, shared_ptr, shared_array, weak_ptr and intrusive_ptr. When using these smart pointers required template type T's destructor can not throw.

To use these smart pointers, you need to join accession:

#include < boost / smart_ptr.hpp>
// Using namespace boost;

(1) scoped_ptr

scoped_ptr packaging the new operator dynamically allocated on the heap object, which has strict ownership, that it can not transfer the wrapped object pointer, once scoped_ptr get over the management of the object, you can not take it back from there. Like its name, as the smart pointers can only be used in this scope, and did not want to be transferred.

Scoped_ptr look at the source code:

template < class T > class scoped_ptr // noncopyable {
private:
    T * px;
    scoped_ptr (scoped_ptr const &);
    scoped_ptr & operator = (scoped_ptr const &);

    typedef scoped_ptr < T > this_type;

    void operator == (scoped_ptr const &) const;
    ! Void operator = (scoped_ptr const &) const;
public:
    typedef T element_type;

    explicit scoped_ptr (T * p = 0): px (p) // never throws {
#if defined (BOOST_SP_ENABLE_DEBUG_HOOKS)
        boost :: sp_scalar_constructor_hook (px);
#endif
    }
#ifndef BOOST_NO_AUTO_PTR
    explicit scoped_ptr (std :: auto_ptr < T > p) BOOST_NOEXCEPT: px (p.release ()) {
#if defined (BOOST_SP_ENABLE_DEBUG_HOOKS)
        boost :: sp_scalar_constructor_hook (px);
#endif
    }
#endif

    ~ Scoped_ptr () // never throws {
#if defined (BOOST_SP_ENABLE_DEBUG_HOOKS)
        boost :: sp_scalar_destructor_hook (px);
#endif
        boost :: checked_delete (px);
    }

    void reset (T * p = 0) // never throws {
        BOOST_ASSERT (p == 0 || p = px!); // Catch self-reset errors
        this_type (p) .swap (* this);
    }

    T & operator * () const // never throws {
        BOOST_ASSERT (px = 0!);
        return * px;
    }

    T * operator -> () const // never throws {
        BOOST_ASSERT (px = 0!);
        return px;
    }

    T * get () const BOOST_NOEXCEPT {
        return px;
    }

#include < boost / smart_ptr / detail / operator_bool.hpp>

    void swap (scoped_ptr & b) BOOST_NOEXCEPT {
        T * tmp = b.px;
        b.px = px;
        px = tmp;
    }
};

 

Scoped_ptr can see the copy constructor and assignment operator (=) are declared as private, thus ensuring scoped_ptr of noncopyable, but also to ensure its management pointer can not be transferred. Also note scoped_ptr can not be compared, because of its two overloaded comparison operators are private.

Note: Due to scoped_ptr not copy and assignment, so it can not be used as elements of the container.

(2) scoped_array

scoped_array like scoped_ptr, its packaging is new [] and delete [] operator.

Here is scoped_ptr part of the source code:

 

template < class T > class scoped_array // noncopyable {
private:
    T * px;
    scoped_array (scoped_array const &);
    scoped_array & operator = (scoped_array const &);

    typedef scoped_array < T > this_type;

    void operator == (scoped_array const &) const;
    ! Void operator = (scoped_array const &) const;

public:
    typedef T element_type;

    explicit scoped_array (T * p = 0) BOOST_NOEXCEPT: px (p) {
#if defined (BOOST_SP_ENABLE_DEBUG_HOOKS)
        boost :: sp_array_constructor_hook (px);
#endif
    }

    ~ Scoped_array () // never throws {
#if defined (BOOST_SP_ENABLE_DEBUG_HOOKS)
        boost :: sp_array_destructor_hook (px);
#endif
        boost :: checked_array_delete (px);
    }

    void reset (T * p = 0) // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) {
        BOOST_ASSERT (p == 0 || p = px!); // Catch self-reset errors
        this_type (p) .swap (* this);
    }

    T & operator [] (std :: ptrdiff_t i) const // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) {
        BOOST_ASSERT (px = 0!);
        BOOST_ASSERT (i> = 0);
        return px [i];
    }

    T * get () const BOOST_NOEXCEPT {
        return px;
    }

#include < boost / smart_ptr / detail / operator_bool.hpp>

    void swap (scoped_array & b) BOOST_NOEXCEPT {
        T * tmp = b.px;
        b.px = px;
        px = tmp;
    }
};

 

Note:
• constructor accepts the new [] results
• * and not overloaded -> operator;
• Providing operator [] operator overloading, you can use the same as ordinary arrays;
• not begin (), end () iterator.

Recommendation: scoped_ptr use or some inflexible First, it provides a pointer value in the form of an array of all the need to use or when to use std :: vector container instead of scoped_ptr better.

(3) shared_ptr

shared_ptr is also packed new operator, but it is the most important point is that it implements the reference counting, so it can be copied and assigned freely, with its name can be shared, when there is no code to use (that is, the reference count is zero time), it was deleted dynamically allocated memory object to be packaged. It can be used as elements of the container.

The following are some of its source code:

 

template < class T > class shared_ptr {
private:
    typedef shared_ptr < T > this_type;

public:
    typedef typename boost :: detail :: sp_element < T > :: type element_type;

    shared_ptr () BOOST_NOEXCEPT: px (0), pn () {}
    template < class Y > explicit shared_ptr (Y * p): px (p), pn () // Y must be complete
    {Boost :: detail :: sp_pointer_construct (this, p, pn);}

    template < class Y, class D > shared_ptr (Y * p, D d): px (p), pn (p, d)
    {Boost :: detail :: sp_deleter_construct (this, p);}

    // As above, but with allocator. A's copy constructor shall not throw.
    template < class Y, class D, class A > shared_ptr (Y * p, D d, A a): px (p), pn (p, d, a)
    {Boost :: detail :: sp_deleter_construct (this, p);}

    template < class Y >
    explicit shared_ptr (weak_ptr < Y > const & r): pn (r.pn) // may throw {
        boost :: detail :: sp_assert_convertible < Y, T > ();
        // It is now safe to copy r.px, as pn (r.pn) did not throw
        px = r.px;
    }

    template < class Y >
    shared_ptr (weak_ptr < Y > const & r, boost :: detail :: sp_nothrow_tag)
    BOOST_NOEXCEPT: px (0), pn (r.pn, boost :: detail :: sp_nothrow_tag ()) {
        if (! pn.empty ()) {
            px = r.px;
        }
    }

    template < class Y >
    shared_ptr (shared_ptr < Y > const & r)

    BOOST_NOEXCEPT: px (r.px), pn (r.pn)
    {Boost :: detail :: sp_assert_convertible ();}

    template < class Y >
    shared_ptr (shared_ptr < Y > const & r, element_type * p) BOOST_NOEXCEPT: px (p), pn (r.pn) {}

    template < class Y, class D >
    shared_ptr (boost :: movelib :: unique_ptr < Y, D > r): px (r.get ()), pn () {
        boost :: detail :: sp_assert_convertible < Y, T > ();
        typename boost :: movelib :: unique_ptr < Y, D > :: pointer tmp = r.get ();
        pn = boost :: detail :: shared_count (r);
        boost :: detail :: sp_deleter_construct (this, tmp);
    }

    shared_ptr & operator = (shared_ptr const & r) BOOST_NOEXCEPT
    {This_type (r) .swap (* this); return * this;}


    template < class Y, class D >
    shared_ptr & operator = (boost :: movelib :: unique_ptr < Y, D > r) {
        boost :: detail :: sp_assert_convertible < Y, T > ();
        typename boost :: movelib :: unique_ptr < Y, D > :: pointer p = r.get ();
        shared_ptr tmp;
        tmp.px = p;
        tmp.pn = boost :: detail :: shared_count (r);
        boost :: detail :: sp_deleter_construct (& tmp, p);
        tmp.swap (* this);
        return * this;
    }

    void reset () BOOST_NOEXCEPT // never throws in 1.30+
    {This_type () swap (* this);.}

    template < class Y > void reset (Y * p) // Y must be complete {
        BOOST_ASSERT (p == 0 || p = px!); // Catch self-reset errors
        this_type (p) .swap (* this);
    }

    template < class Y, class D > void reset (Y * p, D d)
    {This_type (p, d) .swap (* this);}

    template < class Y, class D, class A > void reset (Y * p, D d, A a)
    {This_type (p, d, a) .swap (* this);}

    template < class Y > void reset (shared_ptr const & r, element_type * p)
    {This_type (r, p) .swap (* this);}
    
    // Never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
    typename boost :: detail :: sp_array_access < T > :: type operator [] (std :: ptrdiff_t i) const {
        BOOST_ASSERT (px = 0!);
        BOOST_ASSERT (i> = 0 && (i :: value || boost :: detail :: sp_extent < T > :: value == 0));
        return static_cast < typename boost :: detail :: sp_array_access < T > :: type > (px [i]);
    }

    element_type * get () const BOOST_NOEXCEPT
    {Return px;}

// Implicit conversion to "bool"
#include < boost / smart_ptr / detail / operator_bool.hpp>

    bool unique () const BOOST_NOEXCEPT
    {Return pn.unique ();}

    long use_count () const BOOST_NOEXCEPT
    {Return pn.use_count ();}

    void swap (shared_ptr & other) BOOST_NOEXCEPT
    {Std :: swap (px, other.px); pn.swap (other.pn);}

private:
    template < class Y > friend class shared_ptr;
    template < class Y > friend class weak_ptr;

#endif
    element_type * px; // contained pointer
    boost :: detail :: shared_count pn; // reference counter
};

You can not use static_cast < T * > (sp.get ()) This form will be managed by a shared_ptr pointers display conversion, but also provides a shared_ptr static_pointer_cast < T > (), const_pointer_cast < T > () and dynamic_pointer_cast < T > ( ) corresponding to several member functions. It should also be using the unique (), NA use_count () == 1 in the form.

Also creating shared_ptr can be used when the factory function to create (make_shared < T > ()), which is located in the file make_shared.hpp. When you need to use:

#include < boost / make_shared.hpp >
This is one of make_shared ways:

 

template < class T, class ... Args > typename boost :: detail :: sp_if_not_array < T > :: type make_shared (Args && ... args)
{
    boost :: shared_ptr < T > pt (static_cast < T * > (0), BOOST_SP_MSD (T));

    boost :: detail :: sp_ms_deleter < T > * pd = static_cast < boost :: detail :: sp_ms_deleter < T > * > (pt._internal_get_untyped_deleter ());

    void * pv = pd-> address ();

    :: New (pv) T (boost :: detail :: sp_forward < Args > (args) ...);
    pd-> set_initialized ();

    T * pt2 = static_cast < T * > (pv);

    boost :: detail :: sp_enable_shared_from_this (& pt, pt2, pt2);
    return boost :: shared_ptr < T > (pt, pt2);
}

Note: There are a lot of knowledge about shared_ptr point. . .

(4) weak_ptr

weak_ptr is a smart pointer to tie shared_ptr introduced, the behavior does not have an ordinary pointer, and it does not override operator * and -> operators. For observing the usage share_ptr in the management of resources.

 

template < class T > class weak_ptr
{
private:
    // Borland 5.5.1 specific workarounds
    typedef weak_ptr < T > this_type;

public:
    typedef typename boost :: detail :: sp_element < T > :: type element_type;

    weak_ptr () BOOST_NOEXCEPT: px (0), pn () // never throws in 1.30+ {}

// Generated copy constructor, assignment, destructor are fine ...

#if! defined (BOOST_NO_CXX11_RVALUE_REFERENCES)

// ... Except in C ++ 0x, move disables the implicit copy
    weak_ptr (weak_ptr const & r) BOOST_NOEXCEPT: px (r.px), pn (r.pn) {}

    weak_ptr & operator = (weak_ptr const & r) BOOST_NOEXCEPT {
        px = r.px;
        pn = r.pn;
        return * this;
    }

#endif

    template < class Y >
#if! defined (BOOST_SP_NO_SP_CONVERTIBLE)
    weak_ptr (weak_ptr < Y> const & r, typename boost :: detail :: sp_enable_if_convertible < Y, T> :: type = boost :: detail :: sp_empty ())
#else
    weak_ptr (weak_ptr < Y> const & r)
#endif
    BOOST_NOEXCEPT: px (. R.lock () get ()), pn (r.pn) {boost :: detail :: sp_assert_convertible < Y, T> ();}
#if! defined (BOOST_NO_CXX11_RVALUE_REFERENCES)
    template < class Y>
#if! defined (BOOST_SP_NO_SP_CONVERTIBLE)
    weak_ptr (weak_ptr < Y> && r, typename boost :: detail :: sp_enable_if_convertible < Y, T> :: type = boost :: detail :: sp_empty ())
#else
    weak_ptr (weak_ptr < Y> && r)
#endif
    BOOST_NOEXCEPT: px (. R.lock () get ()), pn (static_cast (r.pn)) {
        boost :: detail :: sp_assert_convertible < Y, T> ();
        r.px = 0;
    }

    // For better efficiency in the T == Y case
    weak_ptr (weak_ptr && r)
    BOOST_NOEXCEPT: px (r.px), pn (static_cast < boost :: detail :: weak_count &&> (r.pn)) {r.px = 0;}

    // For better efficiency in the T == Y case
    weak_ptr & operator = (weak_ptr && r) BOOST_NOEXCEPT {
        this_type (static_cast (r)) .swap (* this);
        return * this;
    }

#endif
    template < class Y>
#if! defined (BOOST_SP_NO_SP_CONVERTIBLE)
    weak_ptr (shared_ptr < Y> const & r, typename boost :: detail :: sp_enable_if_convertible < Y, T> :: type = boost :: detail :: sp_empty ())
#else
    weak_ptr (shared_ptr < Y> const & r)
#endif
    BOOST_NOEXCEPT: px (r.px), pn (r.pn) {
        boost :: detail :: sp_assert_convertible < Y, T> ();
    }
#if! defined (BOOST_MSVC) || (BOOST_MSVC> = 1300)
    template < class Y>
    weak_ptr & operator = (weak_ptr < Y> const & r) BOOST_NOEXCEPT {
        boost :: detail :: sp_assert_convertible ();
        px = r.lock () get ().;
        pn = r.pn;
        return * this;
    }
#if! defined (BOOST_NO_CXX11_RVALUE_REFERENCES)
    template < class Y>
    weak_ptr & operator = (weak_ptr < Y> && r) BOOST_NOEXCEPT {
        this_type (static_cast &&> (r)) .swap (* this);
        return * this;
    }
#endif
    template < class Y>
    weak_ptr & operator = (shared_ptr < Y> const & r) BOOST_NOEXCEPT {
        boost :: detail :: sp_assert_convertible < Y, T> ();
        px = r.px;
        pn = r.pn;
        return * this;
    }
#endif

    shared_ptr < T> lock () const BOOST_NOEXCEPT {
        return shared_ptr < T> (* this, boost :: detail :: sp_nothrow_tag ());
    }

    long use_count () const BOOST_NOEXCEPT {return pn.use_count ();}

    bool expired () const BOOST_NOEXCEPT {return pn.use_count () == 0;}

    bool _empty () const // extension, not in std :: weak_ptr {return pn.empty ();}

    void reset () BOOST_NOEXCEPT // never throws in 1.30+ {this_type () swap (* this);.}

    void swap (this_type & other) BOOST_NOEXCEPT {
        std :: swap (px, other.px);
        pn.swap (other.pn);
    }

    template < typename Y>
    void _internal_aliasing_assign (weak_ptr < Y> const & r, element_type * px2) {px = px2; pn = r.pn;}

    template < class Y> bool owner_before (weak_ptr < Y> const & rhs) const BOOST_NOEXCEPT {return pn
    template < class Y> bool owner_before (shared_ptr < Y> const & rhs) const BOOST_NOEXCEPT {return pn
// Tasteless as this may seem, making all members public allows member templates
// To work in the absence of member template friends. (Matthew Langston)
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
private:
    template < class Y> friend class weak_ptr;
    template < class Y> friend class shared_ptr;
#endif

    element_type * px; // contained pointer
    boost :: detail :: weak_count pn; // reference counter
}; // Weak_ptr

weak_ptr is designed to work with shared_ptr can be from one or another weak_ptr shared_ptr object construction, access to resources observation. But weak_ptr no shared resources, its structure does not cause an increase pointer reference count. Similarly, when weak_ptr destructor will not lead to a reduction reference count.

Use weak_ptr member function use_count () can get shared_ptr's reference count, another expired () function is equivalent to use_count () == 0, but faster, indicating the observed resources no longer exist.

Get this for shared_ptr:

In the file < boost / enable_shared_from_this.hpp> defines a enable_shared_from_this < T> class, it's a summary statement:

 

template < class T> class enable_shared_from_this {
protected:
    enable_shared_from_this () BOOST_NOEXCEPT {}
    enable_shared_from_this (enable_shared_from_this const &) BOOST_NOEXCEPT {}
    enable_shared_from_this & operator = (enable_shared_from_this const &) BOOST_NOEXCEPT {return * this;}
    ~ Enable_shared_from_this () BOOST_NOEXCEPT {}
public:
    shared_ptr < T> shared_from_this () {
        shared_ptr < T> p (weak_this_);
        BOOST_ASSERT (p.get () == this);
        return p;
    }

    shared_ptr < T const> shared_from_this () const {
        shared_ptr < T const> p (weak_this_);
        BOOST_ASSERT (p.get () == this);
        return p;
    }

    weak_ptr < T> weak_from_this () BOOST_NOEXCEPT {return weak_this_;}
    weak_ptr < T const> weak_from_this () const BOOST_NOEXCEPT {return weak_this_;}

public: // actually private, but avoids compiler template friendship issues
    // Note: invoked automatically by shared_ptr; do not call
    template void _internal_accept_owner (shared_ptr < X> const * ppx, Y * py) const {
        if (weak_this_.expired ()) {
            weak_this_ = shared_ptr < T> (* ppx, py);
        }
    }

private:
    mutable weak_ptr < T> weak_this_;
};

When in use simply want to make the management of inherited shared_ptr class from enable_shared_from_this, call the member function shared_form_this () will return to this in shared_ptr. E.g:

#include < boost / enable_shared_from_this.hpp>
#include < boost / make_shared.hpp>
#include < iostream>

class self_shared: public boost :: enable_shared_from_this < self_shared> {
public:
    self_shared (int n): x (n) {}
    int x;
    
    void print () {
        std :: cout << "self_shared:" << x << std :: endl;
    }
};

int main (int argc, char * argv []) {
    std :: shared_ptr < self_shared> sp = std :: make_shared (123);
    sp-> print ();
    std :: shared_ptr < self_shared> p = sp-> shared_from_this ();
    p-> x = 100;
    p-> print ();
    return 0;
}

It should be noted: Do not use shared_from_this from an ordinary object (self_shared Object) () Gets shared_ptr, for example:

self_shared ss;
boost :: shared_ptr < self_shared> p = ss.shared_from_this ();

This will cause the program to run when an attempt to delete an object allocated on the stack when the shared_ptr destructor, undefined behavior occurs.
     
         
         
         
  More:      
 
- Linux command execution judge sentences -;, &&, || (Linux)
- Use mdadm tool to create software RAID 0 (Linux)
- Linux command line ten magic usage (Linux)
- Upgrade to Linux Mint 16 petra Mint 17 Qiana (Linux)
- Linux NIC configuration (Linux)
- Android shutdown (reboot) process (Programming)
- Install Java 8 on Ubuntu using PPA (Linux)
- Use calcurse schedule appointments and to-do in the Linux terminal (Linux)
- Use Vagrant build cross-platform development environment for Python (Server)
- Build Docker based MongoDB replication cluster environment (Database)
- Windows 7 hard disk to install Ubuntu 14.10 (Linux)
- CentOS 6.4 of cron scheduled task configuration (Linux)
- MongoDB relations, references, index query coverage (Database)
- 10046 trace only open for a particular SQL statement (Database)
- Zabbix configure DataGuard monitoring (Database)
- Shuffle Process Arrangement in MapReduce (Server)
- Linux regex awk Comments (Linux)
- PCM audio under Linux (Linux)
- Github with .gitignore ignore specified file (Linux)
- Java singleton mode (Singleton mode) (Programming)
     
           
     
  CopyRight 2002-2022 newfreesoft.com, All Rights Reserved.