C++ without pointers

Started by
11 comments, last by xeyedmary 7 years, 3 months ago

I get C and pointers very well. But I'm trying to use C++ ~without~ standard pointers. It's working for the most part, but now I'm running into an issue:


// MyInterface &something = MyDummyBase(); is defined in the header as a private member


void MyClass::SetSomething(MyInterface &newSomething) {
   something = newSomething;
}

MyInterface &MyClass::GetSomething() {
  return something;
}

Now here's where it gets weird, from the caller:

1. myClassObj.SetSomething(AnotherClass());

2. MyInterface &Value = myClassObj.GetSomething();

At line 1, it calls the constructor of AnotherClass (as expected), sets something to AnotherClass (again, as expected), then calls the destructor of AnotherClass (not expected)

At line 2, it returns MyDummyBase instead. There are no lines inbetween.

All I can think, is that it considers AnotherClass() out of scope now, and destroys it. But what confuses me is, how does it know to revert back to MyDummyBase? I'm trying to do the equiv of .SetSomething(new AnotherClass()), but without raw pointers.

I'm assuming I have to explicitly declare AnotherClass outside of the method, and use it directly in the SetSomething method, but what happened with this logic confounds me.

Any ideas?

[Edit] Nevermind... it's not a pointer, so it can only be set in the constructor. Dur...

Advertisement
You cannot get very far without using just pointers in C++. Eventually you'll run into object lifetime issues. See C++ Faq Lite on references.

In summary:

1. A reference cannot be re-seated.
2. An object must be stored somewhere, and you'll run into object slicing.
3. If you want the benefits of references without the "danger" of pointer (not implying that references are inherently safe), then look into using smart pointers instead.


inb4 Servant of the Lord's in depth explanation!

A) What did you expect to happen in case 1? Why did you expect the destructor to not be called?

B) For case 2 you've invoked assign/copy on the original object. How is that defined (explicit/implicit)?

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

All I can think, is that it considers AnotherClass() out of scope now, and destroys it.

Correct.

MyInterface &something = MyDummyBase(); is defined in the header as a private member

This is also out of scope, gets destroyed, and points at invalid memory. You should've got a compile error, methinks, or at least a warning.

But what confuses me is, how does it know to revert back to MyDummyBase?

It doesn't. It's pointing at invalid memory, and just happens to be acting as if it's pointing at a MyDummyBase.

I'm trying to do the equiv of .SetSomething(new AnotherClass()), but without raw pointers.


Are you aware of smart pointers?

Anyway, what you need to do is:


myClass.SetSomething(object_that_is_guaranteed_to_exist_longer_than_myClass);

'myClass' already exists somewhere. Whereever 'myClass' exists, make sure your interface class is created before it and is destroyed after it.

For example:


int main()
{
    InterfaceNya interface;
    MyClass myClass;
    myClass.SetSomething(&interface);

    //...bunch of code in your program.

    return 0; //'myClass' gets destroyed first, then 'interface'.
}

Are you aware that references are pointers, just with different syntax?
Are you aware that you can call 'new' and give the memory to a reference?
Are you aware that raw pointers aren't bad, and are actively used is clean, modern, C++? (We just don't use raw pointers for *owning* memory)

If this is just for fun and practice, great! But if you think this is the preferred way to program, then you are slightly off-base. smile.png

Yeah, I've done a lot of C so malloc/realloc/free is more natural to me than new/delete, and other C++y things. I also use C# a lot, which has GC, which is a very different beast. C++ feels like a weird middle of the road, not quiet C#, not quite C. I do realize references are pointers, as the only things that actually exist are 64 bit values (or smaller depending on the architecture). You can't actually represent "MyClass" as anything more than a pointer to a block of memory that contains atomic values (int/byte/etc) or pointers (struct/class/etc) as far as passing goes -- it just pushes a pointer to the object onto the stack before calling the method.

So I'll read up on smart pointers, but honestly at this point I might as well just stick with new/delete as it is closer to malloc/free that I'm used to.

Thanks guys!

[Edit]

Yup I switch to standard pointers where it makes sense. I'll use visual leak detector and keep an eye out on things!

I get C and pointers very well. But I'm trying to use C++ ~without~ standard pointers. It's working for the most part, but now I'm running into an issue:


// MyInterface &something = MyDummyBase(); is defined in the header as a private member


void MyClass::SetSomething(MyInterface &newSomething) {
   something = newSomething;
}

MyInterface &MyClass::GetSomething() {
  return something;
}

Now here's where it gets weird, from the caller:

1. myClassObj.SetSomething(AnotherClass());

2. MyInterface &Value = myClassObj.GetSomething();

At line 1, it calls the constructor of AnotherClass (as expected), sets something to AnotherClass (again, as expected), then calls the destructor of AnotherClass (not expected)

At line 2, it returns MyDummyBase instead. There are no lines inbetween.

All I can think, is that it considers AnotherClass() out of scope now, and destroys it. But what confuses me is, how does it know to revert back to MyDummyBase? I'm trying to do the equiv of .SetSomething(new AnotherClass()), but without raw pointers.

I'm assuming I have to explicitly declare AnotherClass outside of the method, and use it directly in the SetSomething method, but what happened with this logic confounds me.

Any ideas?

[Edit] Nevermind... it's not a pointer, so it can only be set in the constructor. Dur...

1- Out of scope.

2- Inheritence.

You're using it wrong.

A) Nothing is wrong with pointers.

B) A better solution is using std::unique_ptr and std::shared_ptr rather than implementating everything with references (which isn't ideal for certian situations).

It does the memory managment you need, not like C# GC but it does deallocates the memory (No need for manual deletion).

C) Use them when an instance owns memory, but when you need to refernece , use a regular pointer. (The instance does not own the memory).

You don't need a pointers in C++ these days. But the biggest problem is the declaration of 'something;. It shouldn't be a reference, it should be value as you intend to rebind it with SetSomething. So remove the reference, and your code will work as expected.

I also use C# a lot, which has GC, which is a very different beast.

If anything they're rather similar, in languages like C# and Java everything is basically a pointer(or acts just like one) maybe I should say pointer with training wheels because the GC handles de-allocation of memory so you can essentially let things go out of scope on a whim. You can get similar behavior in C++ by using smart pointers, but obviously you have to take care of what you're doing.

So I'll read up on smart pointers, but honestly at this point I might as well just stick with new/delete as it is closer to malloc/free that I'm used to.

You're never going to take advantage of the features of a language by just trying to treat it like another language. That'd be like being used to drifting so when you switch to driving a bus you try to drift everywhere. Not super productive.

Smart pointers are a relatively new feature(at least in the standard library) or at least the good ones we have now are. But they're pretty simple to use, unique_ptr can be just thought of as changing the lifetime of a pointer to be just like a stack variable, as soon as it goes out of scope the memory gets freed with it. They're mainly important in C++(besides being nice to use) because C++ has a lot of corner cases with exceptions where things can be left dangling without careful planning. Placing all that load on the destructor means(in every case I can think of anyway) the memory gets freed even if everything comes crashing down.

Sounds like you're avoiding new and delete for some reason I don't quite understand. New and delete are just malloc and free wrapped under the covers. If Malloc and free may seem more natural to you, keep using them, you're going to have a difficult time avoiding heap allocation altogether. Or switch to java, you can new objects all over the place and not worry about deleting them.

This topic is closed to new replies.

Advertisement