Why does the Node destructor get called only once instead of 5 times in the code below?
#include <iostream>
#include <vector>
#include <memory>
struct Node {
~Node() {std::cout << "Node destructor called.\n";}
};
void foo() {
std::vector<std::shared_ptr<Node>> nodes(5, std::make_shared<Node>());
}
int main() {
foo();
std::cout << "foo() ended.\n";
}
The smart pointer destructor contains the call to delete, and because the smart pointer is declared on the stack, its destructor is invoked when the smart pointer goes out of scope, even if an exception is thrown somewhere further up the stack.
The vector will automatically call the destructors of the "smart pointers" and these destructors, in turn, will destroy the pointed objects. This "link" can only be implemented explicitly, inside the "smart pointer's" destructor, which is why ordinary raw pointers can't help you here.
Boost smart pointers by themselves don't have anything to do with the need for a destructor. All they do is remove the need for you to call delete on the allocated memory that they are effectively managing.
char * has no destructor, but vector::clear does call the destructor when the type has it. Yes manual deallocation is necessary unless you store smart_ptr(unique_ptr) in the vector. Formally, your loop has undefined behavior.
Your vector contains five copies of the original shared pointer, all sharing ownership of the one single pointee.
To create five separate objects, each owned by one shared pointer, write it like this:
std::vector<std::shared_ptr<Node>> nodes;
for (int i = 0; i != 5; ++i) nodes.push_back(std::make_shared<Node>());
Kerrek SB explained the situation well, but to do what you want to do in a different way, you could also the std::generate_n
algorithm:
std::vector<std::shared_ptr<Node>> nodes;
std::generate_n(
std::back_inserter(nodes),
5,
std::make_shared<Node>);
This is more along the lines of what you thought you were doing originally.
Or, similarly:
std::vector<std::shared_ptr<Node>> nodes(5);
std::generate(nodes.begin(), nodes.end(), std::make_shared<Node>);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With