Getting a pointer to an object pointed to by a smart pointer - Ivalue error

I'm currently trying to call the sqlite3 library function, and it expects me to pass sqlite3** .

Here is my current code. I have one working part and one part that gives me an error:

 sqlite3 *sqlite = m_db.get(); if (sqlite3_open(std::string(m_dbName.begin(), m_dbName.end()).c_str(), &sqlite)) { } if (sqlite3_open(std::string(m_dbName.begin(), m_dbName.end()).c_str(), &(m_db.get()) )) { } 

The My m_db field is as follows:

 std::unique_ptr<sqlite3> m_db = nullptr; 

Of the two examples I cited, the first works fine. However, the second gives me this error. Note that this comes from the &(m_db.get()) :

 "Address expression must be an lvalue or a function designator" 

I read a little about lvalues ​​and rvalues, but I cannot understand why this syntax is not possible. As far as I understand so far, the problem is that the return value of the .get () operation is just the result of a temporary expression and therefore does not have an identifiable place in memory where I could get the address from.

There must be a way to achieve this in one statement, I think.

Can someone explain to me why this is not working and how can I fix it?

+5
source share
4 answers

The & operator can only be used with an lvalue (or with a qualified identifier when creating pointers to an element). The expression m_db.get() is an rvalue because it returns a pointer by value, not by reference, so you cannot take its address.

unique_ptr does not provide any way to access the base pointer as a reference, you will need to store a copy somewhere like in the first example.

+8
source

The smart pointer stores the pointer and returns it to get. What you want to do here is the opposite: you get a pointer from sqlite3_open and want to save it in a smart pointer. So you would do something like

 sqlite3* db = nullptr; sqlite3_open(..., &db); m_db.reset(db); 

As the main function of unique_ptr should remove the contained pointer in your destructor, I'm not sure if it makes sense to use it here. As I understand it, you should call sqlite3_close returned pointer, and not delete it.

+3
source

There must be a way to achieve this in one statement, I think.

I am not quite sure about this; the point about temporal values ​​can really be that approval is required to get a permanent record.

Plus, you're messing with the semantics of a smart pointer that you shouldn't do - .get really shouldn't be used here.

Soooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo

 your_class::initialize_db() { sqlite3 *sqlite; int retval = sqlite3_open(std::string(m_dbName.begin(), m_dbName.end()).c_str(), &sqlite); if(retval == SQLITE_OK) m_db = std::unique_ptr<sqlite3>(sqlite); } 
+1
source

The lvalue value is basically something that may appear on the left side of the assignment operator. Thus, the error says that you can only get the address of what can be assigned, or a function. This would work if you had member access to the sqlite3 * pointer inside unique_ptr, but you do not, and for good reason.

Moreover, you should not use smart pointer in this case. If sqlite3_open requires the sqlite3 ** argument, then this means that the function will provide a value for the sqlite3 * pointer. This is basically a form of the C # parameter or other such languages. It would be better if it were provided as the result of a function, but this was removed by the result code. This is all good and good, but a smart pointer wants to control this value. You set the value once during initialization, but after that the smart pointer will take care of that. And this is necessary in order to maintain its limitations: the uniqueness of ownership, release, when the pointer itself goes beyond the scope, etc. If you basically go over and rewrite the sqlite3 * pointer inside, then this can no longer be because the smart pointer does not have the ability to intercept the rewrite and release the object that it is currently using.

+1
source

All Articles