1
votes

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.

2
Well, it's passed by value so it'll create a temporary from "user2", and then copy it to value which is used in BindValue. Then the destructors are called at the end of the function and after query->... - Peter Wood

2 Answers

0
votes

Change BindValue to take parameter by const reference.

void BindValue(const char* name, const SQLiteValue &value)
0
votes

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.