passing std::shared_ptr to a function?

Started by
24 comments, last by ZachHoefler 10 years, 7 months ago

I have this code which causes a strange error:


void NBodySim::DrawCSOutput(std::shared_ptr<NBody::Renderer> graphics)
	{
		try
		{
			graphics->SBatch->Begin();

			RECT destRect;
			destRect.left = 0;
			destRect.right = 256;
			destRect.bottom = 256;
			destRect.top = 0;

			graphics->SBatch->Draw(this->uavSrv, destRect);

			graphics->SBatch->End();
		}
		catch(std::exception e)
		{
			const char *wat = e.what();
			int i = 0;
		}
	}

//DrawCSOutput() is called like this:
this->sim.DrawCSOutput(std::shared_ptr<NBody::Renderer>(this->graphics));

//this is the graphics member variable:
Renderer graphics;

I have managed to fix the code by changing the function to take a weak pointer instead but I am wondering, how can I successfully pass std::shared_ptr<T> as an argument to a function?

J.W.
Advertisement

The problem with the code above is that after the function call, the shared pointer will end up with 0 references and destroy the object (as it is the ONLY shared pointer to own that object).

If you would like to pass in a shared_ptr but keep the object alive, store your member as a shared_ptr and then pass it in to the function like so:


void NBodySim::DrawCSOutput(std::shared_ptr<NBody::Renderer> graphics)
	{
		try
		{
			graphics->SBatch->Begin();

			RECT destRect;
			destRect.left = 0;
			destRect.right = 256;
			destRect.bottom = 256;
			destRect.top = 0;

			graphics->SBatch->Draw(this->uavSrv, destRect);

			graphics->SBatch->End();
		}
		catch(std::exception e)
		{
			const char *wat = e.what();
			int i = 0;
		}
	}

//DrawCSOutput() is called like this:
this->sim.DrawCSOutput(this->graphics);

//this is the graphics member variable:
std::shared_ptr<Renderer> graphics;
I don't think you should be using a shared_ptr in this situation. You are only using the parameter graphics inside that function. A shared pointer is useful for storing a pointer to an object long term, but a local variable shouldn't be a shared pointer unless you are passing it to another function that requires a shared pointer. I would use a reference instead.


void NBodySim::DrawCSOutput(NBody::Renderer& graphics)
	{
		try
		{
			graphics.SBatch->Begin();

			RECT destRect;
			destRect.left = 0;
			destRect.right = 256;
			destRect.bottom = 256;
			destRect.top = 0;

			graphics.SBatch->Draw(this->uavSrv, destRect);

			graphics.SBatch->End();
		}
		catch(std::exception e)
		{
			const char *wat = e.what();
			int i = 0;
		}
	}

//DrawCSOutput() is called like this:
this->sim.DrawCSOutput(this->graphics);

//this is the graphics member variable:
Renderer graphics;
My current game project Platform RPG

        catch(std::exception e)
        {
            const char *wat = e.what();
            int i = 0;
        }

'wat' indeed.

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.

By default, pass by const reference, unless you want to write to the original variable also, then pass by reference. Unless that parameter is optional, then pass by pointer.

Unless you want a copy, then pass by value.

If the variable is already in a shared pointer, then pass by const reference to shared pointer. Unless you want to modify the variable, in which case you pass by reference to shared_ptr. Unless you want a copy of the shared_ptr (which doesn't copy the variable the pointer points to), then pass a shared_ptr by value.

Shared pointers delete the variable they point to, after no more of the shared_ptrs are left alive. To protect yourself from these kind of mistakes, a simple trick is to never create a shared_ptr manually, but instead use std::make_shared() for creating shared_ptrs.

But in this situation, all you're wanting to do is make 'NBody::Renderer' accessible to that function. So pass by const reference, if read-only, or regular reference, if read-write. There is no need for a smart pointer to be used here at all.

What is this fad of people using 'this->member' all over the place instead of just referring to members the normal way? It makes my teeth itch.

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.

What is this fad of people using 'this->member' all over the place instead of just referring to members the normal way? It makes my teeth itch.

It's easier to use intelisense with.

What is this fad of people using 'this->member' all over the place instead of just referring to members the normal way? It makes my teeth itch.

It's easier to use intelisense with.

True, but there are also a few minor side effects.

First is that if the class overrides operator-> it will use that instead. This is a fairly rare thing, but something to consider.

Second is that it has the potential to cause some unnecessary trips to memory. Most optimizers will strip that away, but as this is the "General Programming" forum rather than "For Beginners", we should not be over-reliant on the optimizer. I've worked on several systems over the years (Nintendo DS, PalmOS, etc.) that when encountered would dereference the this pointer and follow it rather than use the information already loaded in registers.

My current studio includes it is in our programming style guide as a restricted practice. I flag it in code reviews as an error when I see it.

What is this fad of people using 'this->member' all over the place instead of just referring to members the normal way? It makes my teeth itch.

It's easier to use intelisense with.

True, but there are also a few minor side effects.

First is that if the class overrides operator-> it will use that instead. This is a fairly rare thing, but something to consider.

If class X overloads operator->, that affects using the operator-> on a pointer to X?

What is this fad of people using 'this->member' all over the place instead of just referring to members the normal way? It makes my teeth itch.

It's easier to use intelisense with.


True, but there are also a few minor side effects.

First is that if the class overrides operator-> it will use that instead. This is a fairly rare thing, but something to consider.

Second is that it has the potential to cause some unnecessary trips to memory. Most optimizers will strip that away, but as this is the "General Programming" forum rather than "For Beginners", we should not be over-reliant on the optimizer. I've worked on several systems over the years (Nintendo DS, PalmOS, etc.) that when encountered would dereference the this pointer and follow it rather than use the information already loaded in registers.


My current studio includes it is in our programming style guide as a restricted practice. I flag it in code reviews as an error when I see it.

As pointed out above, overriding -> has no effect on this.

Unless working on a platform where you must use a poor compiler, performing optimizations that the compiler can do for you trivially is premature optimization and should not be a major consideration in program style. A more reasonable objection is that it's verbose, and I think that's the real trade off here. Also using this-> has the advantage that it makes it easy to identify which variables are members.

This topic is closed to new replies.

Advertisement