C ++ smart pointers are confusing
I understand that the use of smart pointers is recommended in the C ++ domain. I have a simple program as shown below.
/* main.cpp */
#include <iostream>
#include <memory>
using namespace std;
/* SQLite */
#include "sqlite3.h"
int main(int argc, char** argv)
{
// unique_ptr<sqlite3> db = nullptr; // Got error with this
shared_ptr<sqlite3> db = nullptr;
cout << "Database" << endl;
return 0;
}
When compiling with the unique_ptr string, an error message appears:
error C2027: use of undefined type 'sqlite3'
error C2338: can't delete an incomplete type
When compiled with a shared_ptr line, this is successful. From several questions and answers, my understanding is that unique_ptr should be preferred as I am not going to have resources to share objects. What's the best solution in this case? Use shared_ptr or fallback to the old approach with null pointers (new / delete)?
source to share
The general approach is in @SomeProgrammerDudes answer (accept it). But for solving your problems, I am posting this.
You don't have to go back to the original new and delete. Not because it sqlite3
is opaque, or because of the overhead std::shared_ptr
. You are using, as pointed out by another answer std::unique_tr
.
The only difference is in how you set up the custom divider. For std::unique_ptr
this is part of the type definition, not a runtime parameter. Therefore, you need to do something like this:
struct sqlite3_deleter {
void operator()(sqlite3* sql) {
sqlite3_close_v2(sql);
}
};
using unique_sqlite3 = std::unique_ptr<sqlite3, sqlite3_deleter>;
source to share
#include <memory>
#include <stdexcept>
/* sqlite 3 interface */
struct sqlite3 {};
extern void sqlite3_close(sqlite3*);
extern int sqlite3_open(sqlite3**);
/* our boilerplate */
struct closer
{
void operator()(sqlite3* p) const
{
sqlite3_close(p);
}
};
using sqlite3_ptr = std::unique_ptr<sqlite3, closer>;
/* handy maker function */
sqlite3_ptr make_sqlite()
{
sqlite3* buffer = nullptr;
int err = sqlite3_open(&buffer);
if (err) {
throw std::runtime_error("failed to open sqlite");
}
return sqlite3_ptr(buffer);
}
int main()
{
auto mysqlite = make_sqlite();
}
source to share