Member-access operator insanity

Started by
3 comments, last by thedevdan 19 years, 6 months ago
(For your information, I have VC2003.NET) I've just rolled and tested my own smart pointer, and it was working perfectly under all tests until I tested it inside of a std::vector. This is when it starts getting weird. From what I know, operator -> keeps applying itself to the returned result until the return result has no operator ->, and it evaluates to that result. Here's what's happenning.
  • The operator -> applied to an iterator stops applying itself when it gets to my smart pointer. So I have to dereference the vector and then call operator ->.
  • After doing that, I get an access violation inside of my operator ->. That didn't make sense to me, because it was working fine before. So, I put a break-point in the code, ran it in debugger, and put the pointer in the 'watch' list. From inside of the member function, the symbol isn't found! At any other point in the code, if I call operator ->, the symbol *is* found, but if I call it from a dereferenced iterator, it isn't! Why would that be happenening? It makes absolutely no sense, and I'll bet it's connected to why I'm getting an access violation.
Here is my code:
template <class Type>
class ValuePointer
{
public:
	ValuePointer() : value_(0)
	{
	}

	ValuePointer(const ValuePointer<Type>& original)
	{
		if (original.value_)
		{
			value_ = new Type(*original.value_);
		}
		else
		{
			value_ = 0;
		}
	}

	ValuePointer(Type* value)
	{
		if (value)
		{
			value_ = new Type(*value);
		}
		else
		{
			value_ = 0;
		}
	}

	ValuePointer<Type>& operator =(const ValuePointer<Type>& original)
	{
		if (original.value_)
		{
			if (value_)
			{
				*value_ = *original.value_;
			}
			else
			{
				value_ = new Type(*original.value_);
			}
		}
		else
		{
			delete value_;
			value_ = 0;
		}
		return *this;
	}

	ValuePointer<Type>& operator =(Type* value)
	{
		if (value)
		{
			if (value_)
			{
				*value_ = *value;
			}
			else
			{
				value_ = new Type(*value);
			}
		}
		else
		{
			delete value_;
			value_ = 0;
		}
		return *this;
	}

	Type& operator *()
	{
		return *value_;
	}

	Type* operator ->()
	{
		return value_; //Break point is here
	}
	
	bool null()
	{
		return !value_;
	}

private:
	Type* value_;
};







Not giving is not stealing.
Advertisement
Quote:This is when it starts getting weird. From what I know, operator -> keeps applying itself to the returned result until the return result has no operator ->, and it evaluates to that result. Here's what's happenning.


Incorrect, operator-> re-applies itself until the returned value is a pointer.

Quote:and I'll bet it's connected to why I'm getting an access violation.


You gave the code for your class. Fine. Give a complete snippet of code that triggers that access violation - so that I can compile and test it.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Oh sorry about that.

#include <vector>#include <iostream>template <class Type>class ValuePointer{public:	ValuePointer() : value_(0)	{	}	ValuePointer(const ValuePointer<Type>& original)	{		if (original.value_)		{			value_ = new Type(*original.value_);		}		else		{			value_ = 0;		}	}	ValuePointer(Type* value)	{		if (value)		{			value_ = new Type(*value);		}		else		{			value_ = 0;		}	}	ValuePointer<Type>& operator =(const ValuePointer<Type>& original)	{		if (original.value_)		{			if (value_)			{				*value_ = *original.value_;			}			else			{				value_ = new Type(*original.value_);			}		}		else		{			delete value_;			value_ = 0;		}		return *this;	}	ValuePointer<Type>& operator =(Type* value)	{		if (value)		{			if (value_)			{				*value_ = *value;			}			else			{				value_ = new Type(*value);			}		}		else		{			delete value_;			value_ = 0;		}		return *this;	}	Type& operator *()	{		return *value_;	}	Type* operator ->()	{		return value_;	}		bool null()	{		return !value_;	}private:	Type* value_;};////class Talker{public:	void Talk()	{		std::cout << "bla bla bla\n";	}};///int main(){	ValuePointer<Talker> t1 = new Talker;	ValuePointer<Talker> t2 = new Talker;	ValuePointer<Talker> t3 = new Talker;	ValuePointer<Talker> t4 = new Talker;	std::vector<ValuePointer<Talker> > v;	v.push_back(t1);	v.push_back(t2);	v.push_back(t3);	v.push_back(t4);	for (std::vector<ValuePointer<Talker> >::iterator t; t != v.end(); ++t)	{		(*t)->Talk(); //Violation is here.  Notice how I have to dereference the iterator.	}		return 0;}


Compile-ready.

EDIT: Could someone move this into General Programming? It's here by accident. Thank you.
Not giving is not stealing.
You forgot to initialize the iterator t.
Adding t = v.begin() to the loop fixes that.

You have to add the dereference because std::vector<T>::iterator::operator->() does return a pointer to T, stopping the chain.

Thread moved as requested.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:Original post by Fruny
You forgot to initialize the iterator t.
Adding t = v.begin() to the loop fixes that.

You have to add the dereference because std::vector<T>::iterator::operator->() does return a pointer to T, stopping the chain.

Thread moved as requested.


Thank you so much, that did the trick! And I now understand why I have to dereference.
Not giving is not stealing.

This topic is closed to new replies.

Advertisement