In C++, is it safe to extend scope via a reference?
In code, what I mean is:
MyCLass& function badIdea()
{
MyClass obj1;
...
return obj1;
}
In C++, is it safe to extend scope via a reference?
In code, what I mean is:
MyCLass& function badIdea()
{
MyClass obj1;
...
return obj1;
}
Please clarify what you do mean.
Assuming you intend to do this:
int * p = NULL;
{
int y = 22;
p = &y;
}
*p = 77; // BOOM!
Then no, absolutely not, scope does not get extended by having a reference.
You may want to look at smart pointers, e.g. from boost libraries: clickety
It is NOT safe to extend the scope via reference. Objects in C are not reference counted when obj1 goes out of scope it will be deleted, refering to the result of badIdea() will only get you into trouble
The only place it's OK to extend a scope with a reference is with a const
reference in namespace
or function scope (not with class members).
const int & cir = 1+1; // OK to use cir = 2 after this line
This trick is used in Andrei Alexandrescu's very cool scope guard in order to capture a const
reference to a base class of the concrete scope guard.
It can be dangerous or useful, depending on your design. Be careful.
class Example
{
public:
Example(A *a) : a_p(a) {};
~Example() {};
private:
A *a_p;
};
const Example &dangerous()
{
A object_a;
Example object_e(&a);
return object_e;
}
// elsewhere in another translation unit...
const Example &e = dangerous();
The final line binds the Example object created within dangerous() so that it's destructor is not called. This is okay and can be applied in a careful design (for instance, supplying a Strategy object as an initialization argument to a constructor).
Emphasis: The problem here is that Example has a pointer data member, which is initialized to point to data that is local to dangerous()'s stack, and goes away once we return from dangerous().
Here is a simplistic example showing how to use const references to attach a default policy to a class constructor:
class BasePolicy
{
// Derive to affect policy, but prefer no data members
public:
BasePolicy() {};
virtual ~BasePolicy() {};
virtual bool serialize_as_binary() { return true; }
};
class DataObject
{
public:
DataObject(const BasePolicy &bp = BasePolicy()) : policy_d(bp) {};
~DataObject() {};
private:
const BasePolicy &policy_d;
};
// elsewhere in another translation unit...
const XmlPolicy &xp = get_xml_policy(); // derived from BasePolicy;
DataObject do(xp);
Here, the reference binds to the data member, and will live as long as do does, regardless of whether the policy object is the supplied default, or an 'outside' object as in the example.