简体   繁体   中英

What return type should I use for a pointer assignment?

I have a struct like this:

struct group
{
    int index; 
    string name; 
    group* child;

};

And I set up a vector to store some group structs.

Now I am trying to have a function to retrieve a group member from that vector by index, something like this:

148    newGroup.child = getGroupByIndex(world, i);

And the definition of the function is :

group& getGroupByIndex(vector<group>* world, int i)
{
    for(vector<group>::iterator it = world->begin();
        it < world->end(); ++it)
    {
        if(it->index == i) return *it;
    }
267     return 0;
}

Unfortunately, it won't even compile.

And the error message is :

tree.cpp: In function ‘int main()’: 
tree.cpp:148: error: cannot convert ‘group’ to ‘group*’ in assignment 
tree.cpp: In function ‘group& getGroupByIndex(std::vector<group, std::allocator<group> >*, int)’: 
tree.cpp:267: error: invalid initialization of non-const reference of type ‘group&’ from a temporary of type ‘int’

My two problems,

  1. how to fix the compile error? what return type should I use?

  2. If I want to return a null pointer in line 267, what should I use? I tried (void *)0 and 0, but neither works.

I think it should be like this:

group* getGroupByIndex(vector<group*> world, int i) // See position of two *
{
    for(vector<group*>::iterator it = world.begin();
        it < world.end(); ++it)
    {
        if(it->index == i)
          return *it;
    }
    return 0;
}

or

group* getGroupByIndex(vector<group> *world, int i) // See position of two *
{
    for(vector<group>::iterator it = world->begin();
        it < world->end(); ++it)
    {
        if(it->index == i)
          return &(*it);
    }
    return 0;
}

If you want prefer references to pointers, you can also define a "not found" group object that will be returned by your function.

I would do that like this :

struct group
{
    int index; 
    string name; 
    group* child;
    group(int i):index(i),child(null){}
    group(int i, const string& n, group& c):index(i), name(n), child(&c){}

    // assuming index defines the uniqueness of your object class
    bool operator == (const struct group& g)const {return (index == g.index);}

    // an unique special instance of group struct
    static struct group not_found;
};
group group::not_found(-1);

thus you can define your function the way you wanted :

group& getGroupByIndex(vector<group>* world, int i)
{
    for(vector<group>::iterator it = world->begin();
        it < world->end(); ++it)
    {
        if(it->index == i) return *it;
    }
    return group::not_found; // a reference to a special singleton instance of struct group
}

and you will be able to make calls like this :

...
group& g = getGroupByIndex(world, index);
if(g == group::not_found)
{
   // handle the not found case here
   ...

Use

boost::optional

First rule of modern C++ : Don't use ****ing pointers.

boost::optional<group&> get(vector<group>& world, int i)
{
    for(auto & grp : world)
    {
        if(grp.index == i)
           return boost::optional<group&>(grp);
    }
    return boost::none;
}

Please note that this solution has O(n) complexity. If you want to search basing on index , I'd recommend using a structure that has references to group objects sorted by index , which would give you O(log n) lookup time.

In that case, I'd probably hold a vector of shared_ptr s and a map<int, weak_ptr> . You could also take a look at boost::multi_index

Ah, and just a sidenote to your 2) point I've just noticed : nullptr .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM