Item 28 of Effective C++ says avoid returning "handles" to object internals
. This question shows how to design your code to do exactly that by thinking about encapsulation in order to avoid accidentally exposing the internals of your class.
My example involves a data array and since memory is an issue I'd like to avoid using std::vector
(and the Boost library).
Using an array here's a very simplified version of my code:
class Foo {
public:
Foo(int size) : data_(new int[size]) {
// Populate with data just for the example
for(int i = 0; i < size; i++) {
data_[i] = i;
}
}
// I know that this isn't good practice
int* const get_data() const {
return data_;
}
~Foo() {
delete[] data_;
}
private:
int* data_;
};
int main(void) {
Foo* foo = new Foo(10);
int* const data = foo->get_data();
delete foo;
// data now dangles which is bad!
return 0;
}
I understand that using const
with get_data()
doesn't make it safe. If I was using a vector I could copy it like the example question above, but since I'd like to avoid this I was wondering how best to design my class to avoid this potentially dangerous situation?
Programming and software design is a constant "choice of one thing over another". If you REALLY can't afford using std::vector
, and you need to expose data to the client-code using your class, then so be it. Document why it is so, and make sure that it's reviewed over time - it may be that when your new model of hardware that has 8MB of RAM instead of 2MB will be able to use the extra 4 bytes that a vector
takes over your plain pointer.
Or write an accessor function:
int& Foo::operator[](int pos)
{
// Add checks here to ensure `pos` is in range?
return data[pos];
}
Now you don't have to return the pointer at all...