I'm trying to keep a reference to a pointer of a different class in my class. I'm trying to see if there is a way to do this without having to define it in the ctor. I cannot make a copy, as I'm using that specific pointer returned to do other things.
class MyClass {
private:
OtherClassPtr &m_ptr_ref;
public:
MyClass();
public:
void MyFunction() {
m_ptr_ref = otherClassPtr->GetPtrRef();
if(!m_ptr_ref)
return;
}
};
A reference needs to be initialized at the point of declaration, and cannot change to refer to a different object during its lifetime. Thus you need to set it in the constructor.
An alternative is to store a pointer. I think of a reference as a pointer with nicer syntax, though the different syntax gives it a different semantic meaning; it acts like the object that it refers to, and so has the same value and the same address as that object. Most relevant to your question, the assignment operator works like assignment to the object, rather than a pointer. This is the reason it cannot change referent.
You can keep a pointer to the pointer:
OtherClassPtr* m_ptr_ref;
/* ... */
m_ptr_ref = &otherClassPtr->GetPtrRef();
An alternative is to use std::reference_wrapper, but that is nothing more than a fancy pointer, and I don't see the advantage over using a pointer.
Related
I have a 'StripManager' class that is responsible for updating the data of an already-existing 'Strip' class. As such, the manager needs a reference to the strip. Now I know I can pass in a pointer to the 'Strip' class to the constructor of the 'StripManager' class, but I'm wondering if there's any way to do that using references instead of pointers. I just have always preferred dealing with references since you use them like the actual class instance rather than having to deal with pointer notation, etc.
So can this be done?
Here's some pseudo-code...
class StripManager
{
public:
Strip &managedStrip;
StripManager(Strip &stripToManage);
}
StripManager::StripManager(Strip &stripToManage)
{
managedStrip = stripToManage;
}
A reference can only be initialized but not assigned. So you cannot reassign the reference itself. You can do it in member initialization list to initialize the reference member.
class StripManager
{
public:
Strip &managedStrip;
StripManager(Strip &stripToManage);
};
StripManager::StripManager(Strip &stripToManage): managedStrip(stripToManage)
{}
You can initialize a reference, but not assign to it, so you need to use the member initializer list for this. It's good habit to use it instead of assignment in constructors anyway as it can be more efficient.
StripManager::StripManager(Strip &stripToManage) : managedStrip (stripToManage)
{
}
Note that having a reference member makes StripManager non-assignable (StripManager a(strip1), b(strip2); a = b; won't compile unless you write a custom assignment operator; even then, since you can't assign references, it's unclear what the semantics should be), which may or may not be a problem depending on your particular situation.
If a C++ class member function requires a pointer to an object as an argument, is it considered bad practice to pass by reference?
The following code, for example, will work, however without the pass by reference it becomes a dangerous code, and will lead to catastrophic errors at runtime.
class ClassA
{
public:
void SetPointer(const ClassB& classb) // Remove 1 ampersand and serious errors will occur
{
if(ptr_to_classb == nullptr) // Initialized to nullptr in constructor
ptr_to_classb = &classb;
else
throw(...); // Throw some error
}
private:
ClassB* ptr_to_classb;
}
Consider if passing by value, and a copy of the argument was made, that this would be disastrous when dereferencing at a later time.
The alternative is this:
class ClassA
{
public:
void SetPointer(const ClassB* const classb)
{
if(ptr_to_classb == nullptr) // Initialized to nullptr in constructor
ptr_to_classb = (ClassB*)(classb);
else
throw(...); // Throw some error
}
private:
ClassB* ptr_to_classb;
}
I like consistency, to defaulted to the first type, however I suspect that the second form is considered to be better practice. Is this the case?
Well, both approaches are correct and fine but in your case it will be probably better to go with pointers, since a reference variable can only be assigned a value at initialization unlike pointers. With the same pointer you could later pass a different class object.
My view is that if passing a null argument to the method is a valid thing to do (i.e. the logic that the method executes would be valid with a null pointer), then use a pointer. If the argument should never be null then use a reference.
In your case this depends on whether it is valid for ClassA::ptr_to_classb to be null. Since you throw if ptr_to_classb is already set (meaning you don't ever want to change what it points to) you might even want to conside storing a reference instead and passing that in the constructor of ClassA, getting rid of ClassA::SetPointer.
There are some other opinions on reference vs pointer here as well.
Your method just sets a field of your object, so it seems you want to use the type of the field (which is pointer, not reference). You wrote
I like consistency, to defaulted to the first type
which, I guess, refers to the rule "use references when possible; use pointers oterwise". I think your case is an exception from this rule, because the declaration
void do_stuff(ClassA& object)
usually means "do stuff on the object, and forget about it", and your case is different.
The question pretty much says it all. I need to initialize a reference to an empty STL container (more precisely, std::set).
Attempting to:
typedef std::set<bozo *> bozo_set;
class BozoClass { public: BozoClass(): bozosetref(bozo_set()) {} }
will obtain compiler errors similar to:
bozo.cc:104: error: invalid initialization of non-const reference of type ‘bozo_set&’ from a temporary of type ‘bozo_set’
(Just a side note: this is not asking whether I should or not use typedef for this or not. I take comments about it, but this isn't really the actual question.)
EDIT: Since there've been a lot of comments about this, the point of having a reference to this is to allow outer classes to change bozo elements of this set, instead of having a ton of unneeded methods in BozoClass to manage the set.
The problem you're having is actually well-described by the compiler error:
invalid initialization of non-const reference of type ‘bozo_set&’ from
a temporary of type ‘bozo_set’
The compiler is telling you that you are trying to take the reference of a temporary. You can't* do this because the thing you are taking a reference to is temporary. In other words, it will cease to exist immediately. The temporary being referred to is the bozo_set you are constructing here:
bozosetref(bozo_set())
^^^^^^^^^^
As soon at the expression bozosetref(bozo_set()) has finished executing, the set instantiated in bozo_set() will be destroyed.
Presumably, bozosetref is a member variable of type set<bozo*>&.
It seems to me like BozoClass is intended to own the set that you are trying to take a reference to. That is fine, but the way you normally do that is by not taking a reference to the set, but by simply instantiating one directly:
class BozoClass
{
public:
BozoClass() {}
private:
set<bozo*> mBozos;
};
Now, mBozos is not a reference to the set, but the set itself.
You can then provide a reference to it to clients of BozoClass through an accessor:
class BozoClass
{
public:
// ...
set<bozo*>& GetBozos() { return mBozos; }
};
Clients can in turn use & modify the set directly through this accessor:
int main()
{
BozoClass bc;
bc.GetBozos().insert (new bozo); // or something
}
Actually, you can but shouldn't do this. Since the set itself hasn't been assigned to a variable, there is nothing "holding" on to it. The reference you took to it becomes invalid.
#include <set>
struct Class {
Class() : set(), setref(set) {}
std::set<void *> set;
std::set<void *> &setref;
};
You cannot pass references to non const objects.
In your case if such thing would be allowed you would get reference to the already deleted temporarily instance of bozo_set in your class, but not a reference to an empty set.
I'm making a little wrapper class for sqlite. To get data to/from the database I have a class called SQLiteValue. When binding data for a query SQLiteValue instances get created on the stack and passed around a few functions. A skeleton outline of the class is below.
class SQLiteValue : public SQLiteObject
{
private:
// stores a pointer to the data contained (could be of varying types)
union
{
int* i;
double* d;
std::string* s;
std::wstring* ws;
BYTE* b;
} pdata;
int type;
public:
SQLiteValue(const char* val);
SQLiteValue(const wchar_t* val);
.. and so on for varying types
virtual ~SQLiteValue();
};
The object gets created by one of several overloaded constructors. The constructors instantiate a "member" of pdata based on their type. This is the important thing for this class. Now, the problem. I have the constructors overloaded so I get clean method calls and don't need to explicitly call SQLiteValue(xxx). As such I don't really want to use references for functions, so I define them like.
void BindValue(const char* name, SQLiteValue value)
query->BindValue(":username", "user2"); // the "clean" method call
Declaring them like this causes a new object to be instantiated every time (or something similar?) I call a function and so the destructor frees memory allocated for pdata. This is bad.
What I'd like to know is this. Is there a better way to achieve what I'm trying to do whilst retaining my clean method calls? At the moment I have private functions which operate by reference which solves the issue, but I don't really like this method. It would be easy for me to forget the reference and I'd end up tracking down this same issue again.
Thanks.
Change BindValue to take parameter by const reference.
void BindValue(const char* name, const SQLiteValue &value)
This is situation when rvalue reference can help. It doesn't reduce amount of constructors/destructors called, but allows to "steal" internal resources of temporary class instances in rvalue (&&) copy constructor or operator=. See details here: http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx
rvalue reference copy constructor just moves another instance internal resources to "this" instance, and resets another instance resources to 0. So, instead of allocation, copying and releasing, it just copies a pointer or handle. "user2" in your code is such temporary instance - rvalue reference.
This can be applied to any C++ compiler implementing C++0x standard.
I wrote a function along the lines of this:
void myFunc(myStruct *&out) {
out = new myStruct;
out->field1 = 1;
out->field2 = 2;
}
Now in a calling function, I might write something like this:
myStruct *data;
myFunc(data);
which will fill all the fields in data. If I omit the '&' in the declaration, this will not work. (Or rather, it will work only locally in the function but won't change anything in the caller)
Could someone explain to me what this '*&' actually does? It looks weird and I just can't make much sense of it.
The & symbol in a C++ variable declaration means it's a reference.
It happens to be a reference to a pointer, which explains the semantics you're seeing; the called function can change the pointer in the calling context, since it has a reference to it.
So, to reiterate, the "operative symbol" here is not *&, that combination in itself doesn't mean a whole lot. The * is part of the type myStruct *, i.e. "pointer to myStruct", and the & makes it a reference, so you'd read it as "out is a reference to a pointer to myStruct".
The original programmer could have helped, in my opinion, by writing it as:
void myFunc(myStruct * &out)
or even (not my personal style, but of course still valid):
void myFunc(myStruct* &out)
Of course, there are many other opinions about style. :)
In C and C++, & means call by reference; you allow the function to change the variable.
In this case your variable is a pointer to myStruct type. In this case the function allocates a new memory block and assigns this to your pointer 'data'.
In the past (say K&R) this had to be done by passing a pointer, in this case a pointer-to-pointer or **. The reference operator allows for more readable code, and stronger type checking.
It may be worthwhile to explain why it's not &*, but the other way around. The reason is, the declarations are built recursively, and so a reference to a pointer builds up like
& out // reference to ...
* (& out) // reference to pointer
The parentheses are dropped since they are redundant, but they may help you see the pattern. (To see why they are redundant, imagine how the thing looks in expressions, and you will notice that first the address is taken, and then dereferenced - that's the order we want and that the parentheses won't change). If you change the order, you would get
* out // pointer to ...
& (* out) // pointer to reference
Pointer to reference isn't legal. That's why the order is *&, which means "reference to pointer".
This looks like you are re-implementing a constructor!
Why not just create the appropriate constructor?
Note in C++ a struct is just like a class (it can have a constructor).
struct myStruct
{
myStruct()
:field1(1)
,field2(2)
{}
};
myStruct* data1 = new myStruct;
// or Preferably use a smart pointer
std::auto_ptr<myStruct> data2(new myStruct);
// or a normal object
myStruct data3;
In C++ it's a reference to a pointer, sort of equivalent to a pointer to pointer in C, so the argument of the function is assignable.
Like others have said, the & means you're taking a reference to the actual variable into the function as opposed to a copy of it. This means any modifications made to the variable in the function affect the original variable. This can get especially confusing when you're passing a pointer, which is already a reference to something else. In the case that your function signature looked like this
void myFunc(myStruct *out);
What would happen is that your function would be passed a copy of the pointer to work with. That means the pointer would point at the same thing, but would be a different variable. Here, any modifications made to *out (ie what out points at) would be permanent, but changes made to out (the pointer itself) would only apply inside of myFunc. With the signature like this
void myFunc(myStruct *&out);
You're declaring that the function will take a reference to the original pointer. Now any changes made to the pointer variable out will affect the original pointer that was passed in.
That being said, the line
out = new myStruct;
is modifying the pointer variable out and not *out. Whatever out used to point at is still alive and well, but now a new instance of myStruct has been created on the heap, and out has been modified to point at it.
As with most data types in C++, you can read it right-to-left and it'll make sense.
myStruct *&out
out is a reference (&) to a pointer (*) to a myStruct object. It must be a reference because you want to change what out points at (in this case, a new myStruct).
MyClass *&MyObject
Here MyObject is reference to a pointer of MyClass. So calling myFunction(MyClass *&MyObject) is call by reference, we can change MyObject which is reference to a pointer. But If we do myFunction( MyClass *MyObject) we can't change MyObject because it is call by value, It will just copy address into a temporary variable so we can change value where MyObject is Pointing but not of MyObject.
so in this case writer is first assigning a new value to out thats why call by reference is necessary.