-
June 15th, 2010, 10:05 AM
#1
[RESOLVED] Pointer of Iterated Object
I am attempting to write a method which iterates over a list, while looking for a particular element of the list and then returns a pointer to that element. My code is pretty ugly, but I don't understand why it doesn't work. The pointer seems to go out of scope right after the calling method.
Code:
Structures::Attribute* getAttribute(Structures::EntityWithAttributes* entityToSearch, std::string attributeToFind){
std::list<Structures::Attribute>::iterator attrIter;
for(attrIter = entityToSearch->attributes.begin(); attrIter != entityToSearch->attributes.end(); attrIter++){
if((*attrIter).name == attributeToFind){
return &(*attrIter);
}
}
// This method is only called when we know the attribute is present, so this shouldn't be reached
return &Structures::Attribute();
}
Any suggestions would be appreciated.
-
June 15th, 2010, 10:37 AM
#2
Re: Pointer of Iterated Object
don't return pointers or references to variables with local scope (= variables defined inside a function).
-
June 15th, 2010, 10:38 AM
#3
Re: Pointer of Iterated Object
I would point out that the std::find() algorithm with an appropriate functor or lambda would serve this purpose.
-
June 15th, 2010, 10:47 AM
#4
Re: Pointer of Iterated Object
Originally Posted by OReubens
don't return pointers or references to variables with local scope (= variables defined inside a function).
In that case, how could I accomplish my goal here?
-
June 15th, 2010, 11:09 AM
#5
Re: Pointer of Iterated Object
Originally Posted by NTL
In that case, how could I accomplish my goal here?
By using the std::find_if algorithm function.
Code:
#include <algorithm>
//...
struct AttributeFinder
{
AttributeFinder(const std::string& theName) : m_name(theName) { }
bool operator() (const Structures::Attribute& attr) const
{ return attr.name == m_name; }
private:
std::string m_name;
};
//...
std::list<Structures::Attribute>::iterator attrIter =
std::find_if( entityToSearch->attributes.begin(),
entityToSearch->attributes.end(), AttributeFinder(attributeToFind));
if ( attrIter != entityToSearch->attributes.end())
return &(*attrIter); // found the attribute
else
return NULL;
In addition, pass strings by reference, not by value.
Regards,
Paul McKenzie
-
June 15th, 2010, 11:27 AM
#6
Re: Pointer of Iterated Object
Originally Posted by Paul McKenzie
By using the std::find_if algorithm function.
Code:
#include <algorithm>
//...
struct AttributeFinder
{
AttributeFinder(const std::string& theName) : m_name(theName) { }
bool operator() (const Structures::Attribute& attr) const
{ return attr.name == m_name; }
private:
std::string m_name;
};
//...
std::list<Structures::Attribute>::iterator attrIter =
std::find_if( entityToSearch->attributes.begin(),
entityToSearch->attributes.end(), AttributeFinder(attributeToFind));
if ( attrIter != entityToSearch->attributes.end())
return &(*attrIter); // found the attribute
else
return NULL;
In addition, pass strings by reference, not by value.
Regards,
Paul McKenzie
Why should I pass the string by reference? The purpose of this method is to match the appropriate attribute (from the existing EntityWithAttributes struct) with a string value which is being read in from a file. Therefore, passing the reference to the string would only be passing a reference to a temporary object.
-
June 15th, 2010, 12:36 PM
#7
Re: Pointer of Iterated Object
Originally Posted by NTL
Why should I pass the string by reference? The purpose of this method is to match the appropriate attribute (from the existing EntityWithAttributes struct) with a string value which is being read in from a file. Therefore, passing the reference to the string would only be passing a reference to a temporary object.
If it's a const reference it's allowed to refer to a temporary. (Unrelated, but FYI: A non-const rvalue reference can also bind to a temporary.) Also, in the event you chose to pass a preexisting string object, it would be slightly more efficient.
It's just the "prefer to pass by const reference rather than by value for non-primitive types" rule of thumb.
-
June 15th, 2010, 12:52 PM
#8
Re: Pointer of Iterated Object
Originally Posted by NTL
Why should I pass the string by reference? The purpose of this method is to match the appropriate attribute (from the existing EntityWithAttributes struct) with a string value which is being read in from a file. Therefore, passing the reference to the string would only be passing a reference to a temporary object.
I am referring to your paramter list:'
Code:
Structures::Attribute* getAttribute(Structures::EntityWithAttributes* entityToSearch, const std::string& attributeToFind
See the item in red?
You are not changing the string passed to you, so the parameter should be a const reference. Passing by value incurs an unnecessary copy operation -- what if the string were 1,000 characters long? Passing by value would make a copy of this string.
Rarely do you ever pass objects by value -- the exception to this are functors.
Regards,
Paul McKenzie
-
June 15th, 2010, 01:32 PM
#9
Re: Pointer of Iterated Object
I believe I understand where you are coming from now, however after making the suggested changes it is still not working properly. Here is an expanded version of the example I provided:
Code:
// attribute structure
struct Attribute
{
std::string name;
double importance;
};
// ... other code
double* importancePtr = &(getAttribute(entityPtr, attributeName)->importance);
Structures::Attribute* getAttribute(Structures::EntityWithAttributes* entityToSearch, std::string attributeToFind){
std::list<Structures::Attribute>::iterator attrIter =
std::find_if( entityToSearch->attributes.begin(),
entityToSearch->attributes.end(), AttributeFinder(attributeToFind));
if ( attrIter != entityToSearch->attributes.end())
return &(*attrIter); // found the attribute
else
return NULL;
}
I would like to note that the above "entityPtr" is retrieved in the same way "getAttribute" works now.
Is there some issue with the way I create the pointer from the structures "importance" value?
-
June 15th, 2010, 01:34 PM
#10
Re: Pointer of Iterated Object
Looks okay to me. What behavior is causing you to think something's wrong?
-
June 15th, 2010, 01:37 PM
#11
Re: Pointer of Iterated Object
Originally Posted by Lindley
Looks okay to me. What behavior is causing you to think something's wrong?
Later on in the program when I try and access the value which is pointed to, it shows up as something like 2.17e-311.
-
June 15th, 2010, 01:48 PM
#12
Re: Pointer of Iterated Object
Is it possible you're deleting that object between this point in the code and when you try to access it?
Since the container is a std::list, accidentally invalidating the pointer due to a container reallocation won't happen, so it would probably need to be an actual erase() call. Either that or the pointer itself is getting corrupted.
Unless---hmmm....make sure that the container you're searching isn't a temporary. If the container itself goes poof, obviously anything pointing to it becomes bad.
-
June 15th, 2010, 02:02 PM
#13
Re: Pointer of Iterated Object
Originally Posted by Lindley
Is it possible you're deleting that object between this point in the code and when you try to access it?
Since the container is a std::list, accidentally invalidating the pointer due to a container reallocation won't happen, so it would probably need to be an actual erase() call. Either that or the pointer itself is getting corrupted.
Unless---hmmm....make sure that the container you're searching isn't a temporary. If the container itself goes poof, obviously anything pointing to it becomes bad.
After going through my code it doesn't seem like the object being pointed to is deleted before I attempt to access it. Also, I have (I believe correctly) used pointers throughout to reference the objects so I don't have a problem with temporary objects disappearing.
Is there any easy/good way to go through and verify my beliefs of these statements?
-
June 15th, 2010, 02:54 PM
#14
Re: Pointer of Iterated Object
Originally Posted by NTL
After going through my code it doesn't seem like the object being pointed to is deleted before I attempt to access it. Also, I have (I believe correctly) used pointers throughout to reference the objects so I don't have a problem with temporary objects disappearing.
Your program crashes, does it not? So how can "good" code crash? You're doing something wrong, and no one knows what it is unless we see the code.
Is there any easy/good way to go through and verify my beliefs of these statements?
What you want is called a "code review", and it takes someone else with experience to look at your code.
Regards,
Paul McKenzie
-
June 15th, 2010, 03:49 PM
#15
Re: Pointer of Iterated Object
Originally Posted by Paul McKenzie
Your program crashes, does it not? So how can "good" code crash? You're doing something wrong, and no one knows what it is unless we see the code.
What you want is called a "code review", and it takes someone else with experience to look at your code.
Regards,
Paul McKenzie
The code doesn't crash. The only reason I know something is up is because I print out the value which is pointed to when I attempt to use it, however the code still executes all the way through.
Is it possible the problem is something other than the pointer losing its value?
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|