views:

135

answers:

4

Consider the following class.

class mapping_items
{
public:

    mapping_items(){}

    void add(const mapping_item* item) {
        items_.push_back( item );
    }

    size_t count() const{
        return items_.size();
    }

    const mapping_item& find(const std::string& pattern){
        const mapping_item* item = // iterate vector and find item;
        return *item; 
    }

private:
    mapping_items(const mapping_items&); // not allowed
    mapping_items& operator=(const mapping_items&); // not allowed
    std::vector<const mapping_item*> items_;
};

C++ FAQ says,

Use references when you can, and pointers when you have to.

So in the above example, should I return const mapping_item& or const mapping_item* ?

The reason why I chose mapping_item& is because there will be always a default return value available. I will never have null returns. So a reference makes it clear that it can't have nulls. Is this the correct design?

+1  A: 

This is seems like an appropriate design choice to me - like the C++ FAQ states - uses references when you can. IMO, unnecessary use of pointers just seems to make code harder to understand.

Ruddy
A: 

Some people say, and I agree,

use pointers if value can be NULL and references otherwise

As to your example, I'd probably go for return const mapping_item;, so by value, to avoid having a reference to a temporary, and hope for my compiler to optimize copying away.

Dmitry
But `mapping_item` has got a vector which has `std::string`. So copying `mapping_item` by value will be costly. I have prevented it by providing private copy constructor and assignment operator.
Appu
+1  A: 

Yes, it's the correct design. Clients can rely on values being non-null.

On a related note, some other class is responsible for managing the lifetime of mapping_item's?

Pointers and ownership easily introduces memory leaks or worse. You might want to consider whether you actually need to store pointers, or if you can get away with copying mapping_item's instead, to avoid memory leaks. However, pointers are necessary if you need to manage subclassed mapping_item's. Pointers are advisable if instances are large or need to be shared.

If you really need pointers, consider using boost::shared_ptr<> rather than raw pointers, both inside your class and as parameter types to e.g. the add() function.

Pontus Gagge
This class will delete items in the vector. I have not shown the destructor in the code. Just to make it simple.
Appu
Thanks for the edit. I will change the code to use shared_ptr.
Appu
BTW, this class is not part of public API. This is used internally and I am the only one who deals with it. So I know where to allocate and deallocate the objects. I am wondering is it worth using `shared_ptr` is such scenarios?
Appu
+2  A: 

There is a problem - what happens if your find() function fails? If this is expected never to happen, you are OK returning a reference (and raise an exception if it happens despite the fact it shouldn't). If on the other hand it may happen (e.g. looking up a name in an address book), you should consider returning a pointer, as a pointer can be NULL, indicating the find failed.

anon
`find` function will never fail. If it couldn't find an item matching the pattern, it returns a default item.
Appu
How is the default item managed? Presumably it is static in the class? If so, then returning a reference should be fine.
anon
It's just another pointer points to a default `mapping_item` instance.
Appu