Allegro.cc - Online Community

Allegro.cc Forums » Game Design & Concepts » Objects and Pointers

This thread is locked; no one can reply to it. rss feed Print
Objects and Pointers
Archon
Member #4,195
January 2004
avatar

I would like to make a distinction between "Objects" and "Pointers" for this thread:
Objects are any old objects which come from a class and which are newed; and Pointers are any old pointers, but they do not new their own objects in the program, but they instead point to existing ones (the objects) -- mostly for "currentObject" referencing.

My first question is, does anyone ever delete objects via the pointer as opposed to the original reference that the objects have (who actually newed the object) ie:

MyClass* myObject = new MyClass();
MyClass* currentObject = myObject;
delete currentObject;

^... with the exception of when an object does not get tracked by the class/function that originates it? eg. BITMAP* load_bitmap(...);

Secondly, would it ever be logical to make a programming language/platform that distinguishes between (this post's definition of) pointers and objects? By doing this, delete cannot be invoked by a pointer.

This could be used as a simple garbage collector: when the original object (variable) is gone, the object in the heap can be de-allocated.

[edit]
This is probably similar to a stack object though...

count
Member #5,401
January 2005

In my understanding of OOP there is no difference between "myObject" and "currentObject". Both are pointers to the same object.
And I don't think that it would make sense to make a language that distinguishes between these two.

Quote:

when the original object (variable) is gone, the object in the heap can be de-allocated.

I don't think that this is a good idea at all. An object should only be deleted by the GC when there is NO pointer pointing to this object.
Otherwise you might end up with a pointer somewhere in your code that still points to this object, but the object is deleted only because your initial pointer has gone... This would force you to keep the initial pointer as long as you need the object.
I think this would be quite a pain in big software projects.

Kibiz0r
Member #6,203
September 2005
avatar

I think you're trying to add complexity where there should be none. The pointers are both pointers, the only object is the one instance of MyClass that they share.

If you need to manage who "owns" an object, use boost::shared_ptr, weak_ptr, or intrusive_ptr.

Archon
Member #4,195
January 2004
avatar

What about the first question?

Kibiz0r
Member #6,203
September 2005
avatar

Well, yeah. Why not? It's the same thing. Sometimes you create an object outside of some class that's meant to manage it or any of a thousand other scenarios.

bamccaig
Member #7,536
July 2006
avatar

There already is a distinction. An object is an instance whereas a pointer stores a memory address that points to that instance.

I'm not really an expert... This may or may not clear things up. :) Sometimes you need to clean it up from an unoriginal pointer because the original pointer is already destroyed, for example.

1// Declaration...
2class EXAMPLE
3{
4public:
5 int UsefulInt;
6};
7 
8class EXAMPLE2
9{
10private:
11 int mintUsefulValue;
12 EXAMPLE *mobjExample;
13public:
14 EXAMPLE2(EXAMPLE *objExample)
15 {
16 this->mobjExample = objExample;
17 }
18 
19 ~EXAMPLE2()
20 {
21 delete this->mobjExample;
22 }
23 
24 int UsefulValue(void)
25 {
26 return(this->mintUsefulValue);
27 }
28 
29 int UsefulValue(int intUsefulValue)
30 {
31 return(this->mintUsefulValue = intUsefulValue);
32 }
33};
34 
35// Implementation...
36 
37EXAMPLE2 *dostuff(void)
38{
39 EXAMPLE *objExample = new EXAMPLE();
40 EXAMPLE2 *objExample2 = NULL;
41 
42 objExample->UsefulInt = 5;
43 
44 objExample2 = new EXAMPLE2(objExample);
45 
46 objExample2->UsefulValue(4);
47 
48 return objExample2;
49}
50 
51int main(int argc, char *argv[])
52{
53 EXAMPLE2 *objExample2 = NULL;
54 
55 objExample2 = dostuff();
56 
57 delete objExample2;
58 
59 return 0;
60}

Out of curiosity, what happens when you do...

1class EXAMPLE
2{
3public:
4 int UsefulInt;
5};
6 
7int main(int argc, char *argv[])
8{
9 EXAMPLE objExample;
10 EXAMPLE *p_objExample = &objExample;
11 
12 delete p_objExample; // Does it freak out here...? Edit: answer=no.
13 
14 objExample.UsefulInt = 5; // Or would it freak out here? Edit: answer=no.
15 
16 return 0;
17}

** EDIT **

Apparently deleting from the stack memory (objExample) isn't possible with the delete keyword so delete p_objExample seemingly does nothing.

anonymous
Member #8025
November 2006

Ideally, the question who owns a pointer should have a very clear answer and a simple policy for each object is never to delete pointers that it hasn't allocated itself, + try to restrict allocation and deallocation to constructor and destructor respectively.

Ownership can be transferred, though, as is the case with smart pointers and pointer containers. However, once you have new-ed an object and handed the pointer over to a smart-pointer class, you'd stop using the original pointer and access the object through its new owner.

As to the OP's question, I wouldn't use two pointers to the same object in the same scope, and normally I wouldn't expect an arbitrary function to deallocate the pointer I pass to it.

In the second code snippet, calling delete on a pointer that hasn't been obtained via new is undefined behaviour.

In the first snippet you must be aware of the restriction that the EXAMPLE2 constructor expects a pointer allocated with new, and will result in undefined behaviour otherwise.

bamccaig
Member #7,536
July 2006
avatar

anonymous said:

In the second code snippet, calling delete on a pointer that hasn't been obtained via new is undefined behaviour.

Surprisingly it compiled fine, but you're right - delete seemingly had no effect on the stack object.

anonymous said:

In the first snippet you must be aware of the restriction that the EXAMPLE2 constructor expects a pointer allocated with new, and will result in undefined behaviour otherwise.

If you passed it the address of a stack object instead would that stack object be destroyed when dostuff() returned or would it remain until the application ended? :-/

// For example...
EXAMPLE2 *dostuff(void)
{
    EXAMPLE objExample;
    EXAMPLE2 *objExample2 = NULL;

    objExample.UsefulInt = 5;

    objExample2 = new EXAMPLE2(&objExample);

    objExample2->UsefulValue(4);

    return objExample2;
}

** EDIT **

I did a test myself and it didn't seem to actually cause any errors, however, the data had changed which leads me to believe that the memory was released when the dostuff() function returned. Notably, however, it didn't cause my program to crash (at least in this instance).

** EDIT **

On second glance, the value I'm getting for objExample2->mobjExample->UsefulInt doesn't seem to be changing when I rerun the program (though it isn't as expected either)... :-/

Kibiz0r
Member #6,203
September 2005
avatar

Good rule of thumb: Don't mix stack and heap objects.

Wetimer
Member #1,622
November 2001

I think you are thinking about ownership.

It seems to me that an object is either owned or shared. Sometimes an object is tied to an owner. It should be destroyed when its owner is destroyed. In other cases, the object should remain alive until everybody is done with it.

Suppose that I have loaded a product from a database. The product itself is held in a Product class. There is another class ProductEditor which handles creating a GUI to actually edit the product. ProductEditor should own the Product. When the window is closed, the Product should be deallocated. In fact, it may be that while the product is open it should be locked to prevent anybody else from opening. Then when deallocated it should release that lock.

I actually dealt with a bug recently where a reference counting pointer was held by another object. Because nothing ever indicated that the object should have been destroyed when the widget was closed, it kept a lock on its record in the database.

I'm not aware of any language that makes this distinction or explicitly deals with ownership. Some widgets libraries would have a parent thing which works somewhat like that.

The question then is how to implement this.

1. When an object is destroyed, you could deallocate all owned objects. But then anybody else who stored a pointer to it for some reason is now dangling.

2. Use a refence counting solution like boost::shared_ptr, so that dangling pointers do not occour. However, here you no long guarantee that the object will be destroyed at the right time.

3. Use a garbage collecting system, but again you have to make sure that no reference are kept or else the garbage will not be collected!

4. Use weak references, such that when the object is destroyed all the weak pointers reset to zero. The thing is in most cases weak references are non-default. So it would be very easy to accidentally have a strong reference defeating the whole thing.

5. If you actually have a notion of a owned object, then when it is destroyed you could assert that the reference count is actually at zero so that you would know that all references have been removed.

<code>if(Windows.State = Crash) Computer.halt();</code>

Go to: