Sign in to follow this  
random_thinker

pointer to a vector of pointers to structs...accessing members

Recommended Posts

random_thinker    282
Hi There is probably a simple solution to this; I keep getting the error message "base operand of `->' has non-pointer type", so I know that this is probably a syntax problem. I have a vector or pointers to structs: typedef vector<Project*> project_vec; I use this in my code generally as follows: project_vec vec_ = new project_vec; ...some method.... { int i = 0; while (!in.fail()) { if ( projectid == in.getString() ) { // Initialize memory. vec_->push_back(new Project); vec_[i]->projectid = projectid; // projectid is a member of struct Project. . . ++i; } } The statement 'vec_[i]->projectid = projectid;' results in a g++ 3.3 compiler error message "base operand of `->' has non-pointer type". Have I missed something simple such as not initializing vec_ correctly, ie vec_() ? Thanks --random

Share this post


Link to post
Share on other sites
Enigma    1410
First, is there a reason you're using a pointer to a vector rather than just a stack-based or static vector? If there is then the syntax you need to access element i is either (*vec_)[i]->projectid; or vec_->operator[](i)->projectid;. This is because vec_ is a pointer. For a pointer the expression pointer[n] is equivalent to *(pointer + n). So vec_[i] has type std::vector< Project * >, but for i != 0 is invalid, since it points to incorrect memory.

Enigma

Share this post


Link to post
Share on other sites
random_thinker    282
Thanks greatly for your help, DigitalD. I've made the code changes and the error messages have disappeared. I prefer the notation '->at(i)->' simply because I find the path to members easier to follow (and there is range checking of course).

Enigma, I've made this a pointer to a vector because I will eventually be creating a lot of runtime vectors that will be passed around and linked to other structures during runtime, as my program grows. The code syntax is a bit more complex this way, but if class design is suitable then eventually the program should be much more flexible.

Originally, I made the system in terms of static vectors, which worked fine, but I started to run into some problems. So I'm in the process of rewriting these parts of the code. Besides, it helps me learn C++ in more depth as well, which is never a bad thing, in my view.

One of the things that I've noticed is that STL container and string class member access changes significantly when the class becomes a pointer. Simple member access syntax goes out the window. For example, when I recently created a pointer to a string map object, I also changed access as follows:

typedef map<string,string> string_map

as non-pointer:
string_map smap;
smap[key] = value;

as pointer:
string_map * smap;
smap->insert(make_pair(key,value));

These types of changes to STL container pointers are not very well documented in existing books. I've tried to get the best references, such as those by Josuttis and Stroustrup, but this useful info is buried deep, if at all there.

I really like utilizing the STL as much as possible in my work, it solves a lot of problems can make result in elegant code, but I wish that these subtleties were better documented.

--random

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Quote:
Original post by random_thinker
as non-pointer:
string_map smap;
smap[key] = value;

as pointer:
string_map * smap;
smap->insert(make_pair(key,value));


For the pointer version, have you tried (*smap)[key] = value ?

Share this post


Link to post
Share on other sites
Enigma    1410
Be aware that map::insert is not equivalent to map::operator[]. map::insert will only ever add a key-value pair to the map and then only if the key is not already in the map. It will never update the value of an existing key-value pair. map::operator[] will either add a key-value pair, or update an existing key-value pair.
#include <iostream>
#include <map>

int main()
{
std::map< int, int > map;
map.insert(std::make_pair(1, 7)); // inserts mapping (1)->(7)
map.insert(std::make_pair(1, 8)); // has no effect
std::cout << map[1] << '\n'; // prints 7
map[2] = 7; // inserts mapping (2)->(7)
map[2] = 8; // updates mapping (2)->(7) to (2)->(8)
std::cout << map[2] << '\n'; // prints 8
}

Enigma

Share this post


Link to post
Share on other sites
random_thinker    282
Thanks for the tip, Anonymous, I'll try it. I would assume that:

(*smap)[key] = value

will behave the same as the non-pointer:

smap[key] = value;

in that one would be able to update a value, as opposed to the pointer version:

smap->insert(make_pair(key,value));

which Enigma (thanks again) correctly pointed out will add new entries, but not update existing keys.

Cheers,

--random.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this