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.
Related
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.
I'm having trouble choosing between two options. If you want to have a function returning a class member by reference, how should the class member be defined ?
MemberClass m_member ?
MemberClass* m_member ?
Let's say m_member is a member of type MemberClass(*) of the class MyClass.
If I do the first option, I have this :
.h
MemberClass &getMember(){return m_member;} //getter to the member, returns by reference
MemberClass m_member;
.cpp
//MyClass constructor
MyClass::MyClass(QObject * parent) :
QObject(parent),
m_member(MemberClass(this)),
...
Second option :
.h
MemberClass &getMember(){return *m_member;} //getter to the member, returns by reference
MemberClass* m_member;
.cpp
//MyClass constructor
MyClass::MyClass(QObject * parent) :
QObject(parent)
{
m_member = new MemberClass(this);
...
What is the best way of doing that ?
Plus, I realised that with the first option I was forced into implementing operator= and copy constructor for MemberClass, why is that ?
EDIT
I want m_member to live outside the class.
MemberClass is in fact a Controller (like in the MVC Design Pattern)
and I have to use it many times in the code.
MyClass is in charge of instanciating the Controller of class
MemberClass and some others and provide a getter to their instance
m_member cannot be NULL
it would be great if m_member was unique, to do that I put its constructor to protected and registered MyClass as a friend class
It actually depends on whether your member can be NULL. If it can not - use first option, if it can - use second one. Also in you first case you should use m_member(this), not m_member(MemberClass(this)).
Also consider adding const getter which can be used on const-objects:
const MemberClass &getMember() const {
return m_member;
}
Also note, that your second code is pretty dangerous. Try to avoid raw pointers when possible and use std::unique_ptr when necessary.
EDIT:
If m_member should be just a reference to some MemberClass than you should never use first option as it is going to create another instance of the MemberClass. In this case use reference MemberClass& m_member if MyClass is guaranteed to live longer than MemberClass and reference should not be changed to point to another instance (because you can't do that with C++ references). Consider using std::shared_ptr<MemberClass> in other cases.
Instead of using a raw pointer or having an automatic object I suggest you use a std::shared_ptr. If you have an automatic storage member like your first example you will not be able to keep it alive after the class is destroyed and allow the object and whatever has a handle to the member to modify the same object. If you use a pointer you can transfer ownership but know you class gets more complicated as you have to implement the rule of 3 and you have to keep track of who has a handle.
If you use a std::shared_ptr then you can return that pointer by value from getMember and now whoever got that handle shares in the ownership of the member. If the object is destroyed then whoever still has handle still has a valid object as there are still instances of the pointer in your code. If all of the things who had a handle to the member are gone and then you object is destroyed the pointer will be deleted for you as the last holder of the pointer was destroyed. Now there is no more manual memory management, the default constructors will work and you have expressed your intent on how the ownership of member should behave. That's a win-win-win.
I believe the first way is the better way of doing it, as it'll allow you to avoid allocating memory on the heap and dealing with the cleanup of that pointer. In addition, you get to reap the small performance benefit of using member initialization list. However, in both cases you have to face the possibility of the reference to the member variable living longer than the object, which can cause issues.
As for why you were forced to implement operator= and copy constructor, I'm unsure, but unless you declare your constructor as 'explicit', it might want to force you to deal with situations where someone says:
QObject* q = new QObject;
MyClass myObj = q;
As this would cause an implicit conversion.
In C++11, you might be able to delete the operator= and copy constructor instead of defining them though:
MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;
I'm not a very experienced c++ coder and this has me stumped. I am passing a object (created elsewhere) to a function, I want to be able to store that object in some array and then run through the array to call a function on that object. Here is some pseudo code:
void AddObject(T& object) {
object.action(); // this works
T* objectList = NULL;
// T gets allocated (not shown here) ...
T[0] = object;
T[0].action(); // this doesn't work
}
I know the object is passing correctly, because the first call to object.action() does what it should. But when I store object in the array, then try to invoke action() it causes a big crash.
Likely my problem is that I simply tinkered with the .'s and *'s until it compiled, T[0].action() compliles but crashes at runtime.
The simplest answer to your question is that you must declare your container correctly and you must define an appropriate assigment operator for your class. Working as closely as possible from your example:
typedef class MyActionableClass T;
T* getGlobalPointer();
void AddInstance(T const& objInstance)
{
T* arrayFromElsewhere = getGlobalPointer();
//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **objects**
//whose first element we don't mind losing
//**copy** the instance we've received
arrayFromElsewhere[0] = objInstance;
//now invoke the action() method on our **copy**
arrayFromElsewhere[0].action();
}
Note the signature change to const reference which emphasizes that we are going to copy the original object and not change it in any way.
Also note carefully that arrayFromElsewhere[0].action() is NOT the same as objInstance.action() because you have made a copy — action() is being invoked in a different context, no matter how similar.
While it is obvious you have condensed, the condensation makes the reason for doing this much less obvious — specifying, for instance, that you want to maintain an array of callback objects would make a better case for “needing” this capability. It is also a poor choice to use “T” like you did because this tends to imply template usage to most experienced C++ programmers.
The thing that is most likely causing your “unexplained” crash is that assignment operator; if you don't define one the compiler will automatically generate one that works as a bitwise copy — almost certainly not what you want if your class is anything other than a collection of simple data types (POD).
For this to work properly on a class of any complexity you will likely need to define a deep copy or use reference counting; in C++ it is almost always a poor choice to let the compiler create any of ctor, dtor, or assignment for you.
And, of course, it would be a good idea to use standard containers rather than the simple array mechanism you implied by your example. In that case you should probably also define a default ctor, a virtual dtor, and a copy ctor because of the assumptions made by containers and algorithms.
If, in fact, you do not want to create a copy of your object but want, instead, to invoke action() on the original object but from within an array, then you will need an array of pointers instead. Again working closely to your original example:
typedef class MyActionableClass T;
T** getGlobalPointer();
void AddInstance(T& objInstance)
{
T** arrayFromElsewhere = getGlobalPointer();
//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **pointers**
//whose first element we don't mind losing
//**reference** the instance we've received by saving its address
arrayFromElsewhere[0] = &objInstance;
//now invoke the action() method on **the original instance**
arrayFromElsewhere[0]->action();
}
Note closely that arrayFromElsewhere is now an array of pointers to objects instead of an array of actual objects.
Note that I dropped the const modifier in this case because I don’t know if action() is a const method — with a name like that I am assuming not…
Note carefully the ampersand (address-of) operator being used in the assignment.
Note also the new syntax for invoking the action() method by using the pointer-to operator.
Finally be advised that using standard containers of pointers is fraught with memory-leak peril, but typically not nearly as dangerous as using naked arrays :-/
I'm surprised it compiles. You declare an array, objectList of 8 pointers to T. Then you assign T[0] = object;. That's not what you want, what you want is one of
T objectList[8];
objectList[0] = object;
objectList[0].action();
or
T *objectList[8];
objectList[0] = &object;
objectList[0]->action();
Now I'm waiting for a C++ expert to explain why your code compiled, I'm really curious.
You can put the object either into a dynamic or a static array:
#include <vector> // dynamic
#include <array> // static
void AddObject(T const & t)
{
std::array<T, 12> arr;
std::vector<T> v;
arr[0] = t;
v.push_back(t);
arr[0].action();
v[0].action();
}
This doesn't really make a lot of sense, though; you would usually have defined your array somewhere else, outside the function.
I have a class which basically is a text manager. It can draw text and whatnot. I basically want the color and text std::string to only be a constant reference. Would it then be alright to do
class TextManager {
const std::string &text;
void draw(const std::string &text) const;
public:
TextManager(const std::string &text)
{
this->text = text;
}
void someMethod()
{
draw(text);
}
};
I want when the class that owns an instance of TextManager's text changes, the change is reflected in the TextManager.
would I be better off using a pointer?
thanks
If you never need to re-seat the reference (i.e. refer to a different object), then it's fine. But in my experience, you'll inevitably find out later down the line that you need to be more flexible, in which case a reference is a pain. It may be better to go with a pointer from the start.
But note that you can only initialise a member variable of reference type in the constructor initialiser list. (Also, you probably want to declare that constructor as explicit).
This code doesn't compile. this->text = text doesn't do what you think it does - it's not like Java where assigning a reference is like changing the pointer. reference = value will actually invoke the copy operator, so it will copy the value of the rhs to the lhs, either as member-by-member copy or using the operator= if it was overridden. Since your text is const, you can't do that.
So in this case, you have to use a pointer - references cannot be modified once initialized.
EDIT: Just to explain ways in which you could use a reference:
const std::string &text = yourString;
or:
TextManager(const std::string &textRef)
: text(textRef)
{
}
That way, you have a permanent reference to whatever string you have.
Once you have sorted out the initialisation (which other comments can help you with), using a reference will let you do what you want. That is, changes to the referenced std::string will affect your class because they are the same std::string.
You can get similar behaviour using std::string const* instead of std::string const&. As Oli brought out, using a pointer is more flexible. Since a pointer can be null and can be updated using a pointer will allow you to define a default constructor and a (probably compiler generated) assignment operator. Which may not be important in this class but likely will be in some other class you will write (eg if you want to put objects of this class into a std::vector). So you probably are better off using a pointer internally. Though you may wish to still pass a reference to the constructor and take the address of it to initialise the member.
I've stumbled onto something I can't figure out, so I think I'm missing something in the greater C++ picture.
In short, my question is: how to keep a mutable, non-deletable, possibly NULL instance of an object in a class.
The longer version is:
I have the following scenario: a bunch of classes (which I can change slightly, but not thoroughly refactor), most of which need to use an object. This object, while mutable, is managed by someone else so it must not be deleted.
Some of the classes in the bunch do not need such an object - they reuse code from other classes, but through the available parameters supplied to these classes it is guaranteed that even if an object is supplied, it will not be used.
The current implementation uses a pointer-to-const-object (const Obj *). This, in turn, means all the object's methods must be const and most fields mutable. This is a messy solution since the fields declared mutable are available for inspection (so quite the opposite of the c++ lite entry here). It also only partially solves the "do-not-delete-this-here" issue (compiler does not complain but a const in front of the object is an indication).
If I used a reference to this object, I'd force some callers to create a "dummy" object and provide it to the class they are instantiating. This is also messy, besides being a waste of resources. I cannot create a global object to can stand in for a "NULL" reference due to project restrictions.
I feel that the reference is the tool I need, but I cannot refactor the classes involved to such an extent as to have the object disappear from their implementations where it is not used (it can be done, but it is not simple and it would not be fast). So I want to implement something simpler, which will just draw an alarm signal if anyone tries to misuse this object, but keeps my object mutable.
The best solution I can think of is using a const-pointer-to-object (Obj * const) - this does not make the compiler complain, but I have my mutable object and a sort-of alarm signal -through the const - in place as well.
Does anyone have a better idea ?
I've traditionally seen these kind of scenarios implemented using a shared_ptr/weak_ptr combo. See here.
The owner/deleter would get a
boost::shared_ptr<T>
Your class would get a
boost::weak_ptr<T>
To reassign the weak ptr, simply reassign the pointer:
void MyClass::Reassign(boost::weak_ptr<T> tPtr)
{
m_tPtr = tPtr;
}
To use the weak ptr, first check to see if it's still around:
void MyClass::Use()
{
boost::shared_ptr<T> m_temporarySharedPtr = m_tPtr.lock();
if (m_temporarySharedPtr)
{
//...
}
}
The weak ptr can be made "NULL" by reseting it, or assigning it to an empty shared_ptr
void MyClass::MakeNull()
{
m_tPtr.reset();
}
You can make the destructor of that object private. That will trigger compile time error on attemp to delete object. Also you should allow restcted code to delete object by using friends mechanism or member function.
You can put a wrapper around the pointer to allow modification but not deletion:
template <typename T> class Wrapper
{
public:
Wrapper(T *p=0) : pointer(p) {}
T *operator->() {return pointer;}
T const *operator->() const {return pointer;}
operator bool() const {return pointer;}
private:
T *pointer;
};
You can use this just like a pointer to the template type in some contexts, but can't call delete on it. The wrapped type must be a struct or class type (i.e. a type where -> makes sense). Then one of your classes that uses, but doesn't manage the lifetime of, the object would look a bit like this:
class User
{
public:
void Assign(Object *o) {object = o;}
void UseObject() {if (object) object->Use();}
private:
Wrapper<Object> object;
};
Technically, you can still get at the raw pointer, but the code to do it is very wrong-looking:
delete wrapper.operator->();
Sounds like a case for a shared_ptr.
An alternative (if allowed by your restircitons) would be to create a dummy object similar to a shared pointer to act as a wrapper between the object in question and your classes.
Your classes can attempt to delete this object if they wish, but it itself will leave the original object untouched. Overload the * operator and you can use it transparently.
something like this?...
the Obj class is an aggregation of your new class, you point at it with an Obj* cont pObj, which you set up at the creation of your new class (or leave as 0 if it's not used), you then check pObj before calling any of its functions?
if ( pObj ){ pObj->foo(); }
if the function foo's incorrectly defined as mutable then you need to fix its declaration.
your new class isn't responsible for cleaning up/deleting the Obj class.