OSG smart pointer

Source: Internet
Author: User

From: Don burns using reference pointers in producer and openscenegraph

Ref_ptr <> manages the memory allocated to the heap by reference count. When the count is (0), the memory is automatically released.

Rule 1:
Ref_ptr is used for all classes inherited from referenced. <>
Rule 2:
Never return the address pointed to by ref_ptr, and returns ref_ptr itself
Rule 3:
Never use REF (), unref (), (or release (), unref_nodelete () unless you really know what you are doing
Rule 4:
Any referenced derived class (whether direct or indirect), The Destructor must be set to protected so that the object will not be allocated to the stack.
Rule 5(Exception in rule 1 ):
When cyclically referencing, when we know that this object will be referenced by another ref_ptr within the current range, It is necessary (Be careful) to use a simple pointer.

========================================

First, make it clear:

1. The memory allocated to heap refers to those dynamically allocated by calling methods such as new () or malloc, the programmer is responsible for tracking and recycling (delete and free), otherwise it will cause memory leakage. The memory allocated on the stack is managed by the compiler, so we don't have to worry about it, for example, local variables.

2. Reference count is used to manage objects allocated to the stack. If an external entity needs to use this object, the reference count is + 1. When it is used up,-1 is used up. When it is reduced to 0, the object will release itself.

====================================

Ref_ptr <>:

Ref_ptr <> is a template class that can be instantiated as a pointer to any object inherited from referenced. Strictly speaking, ref_ptr <> itself is allocated on the stack, but stores the address of memory allocated on the stack. Its function is to implement automatic reference counting: The reference counting of the objects referred to by ref_ptr <> is + 1 When copying constructors or "=" operators, in The Destructor-1.

Now compare:

Void someclass: somemethod ()
{
OSG: ref_ptr noderefptr = new OSG: node;
OSG: node * nodeptr = new OSG: node;
}

When the above function is returned, noderefptr calls its destructor. The reference count of the object is reduced to (0), and the object Automatically releases itself. nodeptr is invalid outside the function, the memory it originally points to remains in the heap and cannot be tracked.

Let's look at this example again:

Void someclass: somemethod (OSG: Group * Group)
{
OSG: ref_ptr noderefptr = new OSG: node;
Group-> addchild (noderefptr. Get ());
}

The ref_ptr of the Group in the function increases the reference count of the object to (2). When the function returns, the noderefptr destructor reduces the count of the object to (1 ), so when the group is still using this object, it will not release itself. For. Get (), it can be understood as returning the address of the OSG: Node object.

Generally, bool valid () is used to determine whether a smart pointer points to a valid address.

==================================

Notes:

1. Mix * And ref_ptr <>

Looking at the following code, the dosomethingwithnode function uses ref_ptr <> to increase the reference count of an object to (1), and then decreases the return value to (0). At this time, the object releases its memory. An error occurs when dosomestuff () operates on that memory.

Void someclass: dosomethingwithnode (OSG: node * node)
{
OSG: ref_ptr nptr = node;
Nptr-> doit ();
}
Void someclass: dosomestuff ()
{
OSG: node * node = new OSG: node;
Dosomethingwithnode (node );
Node-> doitagain (); // The node now points to the deleted data, causing access violation
}

Rule 1:
Ref_ptr is used for all classes inherited from referenced. <>

---------------------------------

2. Use ref_ptr <> as the function return value

In the following code, the createanode () is dynamically allocated and is released when it exits. initializeorsomething () cannot add reference count before it is released.

Void someclass: initializeorsomething ()
{
OSG: ref_ptr noderefptr = createanode ();
}
OSG: node * someclass: createanode ()
{
// Follow Rule 1
OSG: ref_ptr nrefptr = new OSG: node;
Return nrefptr. Get (); // The directed memory will be released when the function exits.
}

There are two solutions:
1) In createanode (), no ref_ptr <> may cause memory leakage;
2) manually add the Count nrefptr-> REF () and call unref () by yourself ()

So it is best to use ref_ptr as the return value:

OSG: ref_ptr someclass: createanode ()
{
OSG: ref_ptr nrefptr = new OSG: node;
Return nrefptr; // OK!
}

Rule 2:
Never return the address pointed to by ref_ptr, and returns ref_ptr itself
Rule 3:
Never use REF (), unref (), (or release (), unref_nodelete () unless you really know what you are doing

---------------------------------

3. Objects inherited from referenced by unsuitable applications

The base classes of OSG and producer define their destructor as protected, and force users to allocate these classes to the stack instead of the stack. However, the mynode defined below is valid, and its destructor is set to public. In this way, the programmer can legally (but improperly) place this class as a local variable on the stack. If a ref_ptr <> references it, the reference count will be reduced to (0 ), as a result, the stack variable tries to delete itself.

Class mynode: Public OSG: Node
{
Public:
Mynode (){}
Virtual ~ Mynode () {}// public destructor
}
Void someclass: dosomething ()
{
Mynode;
Dosomethingwithmynode (& mynode );
}
Void someclass: dosomethingwithmynode (mynode * n)
{
OSG: ref_ptr mnrefptr = N;
}

Rule 4:
Any referenced derived class (whether direct or indirect), The Destructor must be set to protected so that the object will not be allocated to the stack.

---------------------------------

4. circular reference

When two class instances inherited from referenced reference each other, it may cause loop reference.

Class B;

Class A: Public OSG: referenced
{
Public:
A (){}
Void SETB (B * B );
PRIVATE:
OSG: ref_ptr _ B;
};

Class B: Public OSG: referenced
{
Public:
B (A * A): _ A (){}
PRIVATE:
OSG: ref_ptr _;
};

Void A: SETB (B * B) {_ B = B ;}

Int main ()
{
OSG: ref_ptr A = new A; // (A's count is 1)
OSG: ref_ptr B = new B (A. Get (); // (B's count is 1 and A's count is 2)
A-> SETB (B. Get (); // (B's count is 2)
Return 0;
}
// A and B are invalid here. The reference count is-1 and changes to (1). The object is not deleted.

The solution is to use a simple pointer:

Class B;

Class A: Public OSG: referenced
{
Public:
A (): _ B (0l ){}
Void SETB (B * B );
PRIVATE:
// Not a ref pointer
B * _ B;
};

Class B: Public OSG: referenced
{
Public:
B (A * A): _ A (){}
PRIVATE:
// Not a ref pointer
A * _;
};

Void A: SETB (B * B) {_ B = B ;}

Int main ()
{
OSG: ref_ptr A = new A; // & A's count is 1
OSG: ref_ptr B = new B (A. Get (); // & B's count is 1 and & A's count remains 1
A-> SETB (B. Get (); // & B's count remains 1
Return 0;
}
// A and B Go out of scope, counts go to 0

Rule 5 (except rule 1 ):
When cyclically referencing, when we know that this object will be referenced by another ref_ptr within the current range, It is necessary (Be careful) to use a simple pointer.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.