I am learning about memory management and not quite sure how how to manage the delete and/or destructor policy.
Suppose I have the following template:
template <typename X>
class DBContainer {
private:
vector<vector<X>> db;
size_t dbSize;
public:
DBContainer(size_t n = 100) {
dbSize = n;
<vector<vector<X>> *tmp = new vector<vector<X>>(dbSize);
db = std::move(*tmp);
// db = std::swap(tmp);
delete tmp;
}
~DBContainer() { /* how should I delete `db`? */ }
// ~DBContainer() = default;
};
How should I set the destructor policy for db
? I understand that for a raw pointer, std::move
only copies the intermediary vector of vectors to db
; therefore, I still need to delete the intermediary dynamically allocated vector. I could be wrong but I believe it is the same for std::swap
.
But then, at the end of the program, how should I manage the destructor policy for db
? Do I simply set it to default?
Anything you construct dynamically with new
needs to be delete
'd when you are done using it. std::unique_ptr
can help with that by calling delete
for you when it is itself destructed, eg:
template <typename X>
class DBContainer {
private:
vector<vector<X>> db;
size_t dbSize;
public:
DBContainer(size_t n = 100) {
dbSize = n;
std::unique_ptr<vector<vector<X>>> tmp(new vector<vector<X>>(dbSize));
// or: auto tmp = std::make_shared<vector<vector<X>>>(dbSize);
db = std::move(*tmp);
} // <-- tmp is destroyed here, delete'ing the temp vector
//~DBContainer() = default;
};
It doesn't matter that the content of tmp
is moved to db
, tmp
itself still needs to be delete
'd.
However, since db
is not being dynamically constructed via new
, there is no need to delete
it. It will be destructed automatically when its owning DBContainer
object is destructed. Only your temporary vector
that is being constructed via new
needs to be delete
'd. But even that can be avoided, by simply not constructing the temporary vector
dynamically at all, eg:
template <typename X>
class DBContainer {
private:
vector<vector<X>> db;
size_t dbSize;
public:
DBContainer(size_t n = 100) {
dbSize = n;
vector<vector<X>> tmp(dbSize);
db = std::move(tmp);
} // <-- tmp is destroyed here
//~DBContainer() = default;
};
Alternatively:
template <typename X>
class DBContainer {
private:
vector<vector<X>> db;
size_t dbSize;
public:
DBContainer(size_t n = 100) {
dbSize = n;
db = vector<vector<X>>(dbSize); // <-- temp destroyed after operator= exits
}
//~DBContainer() = default;
};
That being said, you don't actually need the temporary vector
at all. You can (and should) initialize db
directly, in the constructor's member initialization list, eg:
template <typename X>
class DBContainer {
private:
vector<vector<X>> db;
size_t dbSize;
public:
DBContainer(size_t n = 100) : db(n), dbSize(n) { }
//~DBContainer() = default;
};
And technically, you can get rid of dbSize
too, just use db.size()
whenever needed:
class DBContainer {
private:
vector<vector<X>> db;
public:
DBContainer(size_t n = 100) : db(n) { }
//~DBContainer() = default;
};