Quote Originally Posted by Daved View Post
>> Because if somehow the pointer counter reaches 0 while the function is using it, it will use freed memory and crash.
It can't happen. Pretend the function is inline, then move the code from the function into the calling code. You're not calling any functions at that point. If you assume that code without function calls is safe, then code with function calls and pass by reference is safe.

Assuming the constructor(s) increment the count, destructors decrement the count, and copying of the pointer is handled properly, there is no way there can be an issue. If you have a multi-threaded environment, then you need to put some sort of synchronization control around the decrement and delete areas, but that's not a problem for the code that uses the class.
Can't happen you say? I have a situation where it DOES happen. Consider this:
Code:
struct foo_s
{
	ppnew<int> pint;
};

void foo2(pp<int>& pTest)
{
	Sleep(10000);
	int n = *pTest;
	n;
}

void foo3(pp<int> pTest)
{
	Sleep(10000);
	int n = *pTest;
	n;
}

DWORD WINAPI foo(void* pParameter)
{
	foo_s* p = (foo_s*)pParameter;
	foo2(p->pint);
	//foo3(p->pint); // Works if you call this function instead.
	return 0;
}

BOOL CKantanAnimeApp::InitInstance()
{
	foo_s* ps = new foo_s;
	*ps->pint = 100;
	//NewThread(&CKantanAnimeApp::foo, this, ps->pint);
	::CreateThread(NULL, NULL, &foo, ps, NULL, NULL);
	Sleep(1000);
	int n = *ps->pint;
	n;
	delete ps;
	Sleep(100000);
	...
}
When foo2 tries to access the memory, an access violation occours. Uncomment foo3 and comment out foo2 and there will be no access violation. The only difference is that foo2 takes a reference and foo3 takes by value.