Sta*_*nny 1 c++ memory-management allocation vector shared-ptr
假设这个类Foo:
struct Foo {
std::shared_ptr<int> data;
std::shared_ptr<std::vector<Foo>> foos;
};
Run Code Online (Sandbox Code Playgroud)
它有一个指向int的指针
它有一个指向此程序中将存在的所有实例的指针(因此其中一个实例== *this)
让我们创建一个实例Foo并在添加一些实例后查看use_count()其.data成员变量.foos:
int main() {
Foo foo;
foo.data = std::make_shared<int>(5);
foo.foos = std::make_shared<std::vector<Foo>>();
foo.foos->resize(8);
for (auto & f : *foo.foos) {
f.data = foo.data;
f.foos = foo.foos;
}
std::cout << "use count: " << foo.data.use_count() << '\n';
}
Run Code Online (Sandbox Code Playgroud)
输出:
use count: 9
Run Code Online (Sandbox Code Playgroud)
哪个好(1 foo+ 8 .foos).但是,似乎在main()返回时,仍会有9个 8指针指向.data!这可以通过放入foo本地范围并让一个额外的指针.data指向use_count()以后观察这个指针来证明:
int main() {
std::shared_ptr<int> ptr;
std::cout << "use count | before: " << ptr.use_count() << '\n';
{ //begin scope
Foo foo;
foo.data = std::make_shared<int>(5);
foo.foos = std::make_shared<std::vector<Foo>>();
foo.foos->resize(8);
for (auto & f : *foo.foos) {
f.data = foo.data;
f.foos = foo.foos;
}
ptr = foo.data;
std::cout << "use count | inside: " << ptr.use_count() << '\n';
} //end scope
std::cout << "use count | after: " << ptr.use_count() << '\n';
}
Run Code Online (Sandbox Code Playgroud)
输出是:
use count | before: 0
use count | inside: 10
use count | after: 9
Run Code Online (Sandbox Code Playgroud)
哪个不好.我会excpect use count | after是1因为foo其所有成员应在范围到底得的解构.好吧,foodefinetely得到解构(否则use_count | after将是10和不9)但其.foos矢量指针没有被解构.而且ptr只是一个std::shared_ptr<int>,因此根本没有任何关系struct Foo.所有这些都可以是固定的通过提供struct Foo一个析构函数,其reset()S上的.foos->data手动指针:
#include <memory>
#include <iostream>
#include <vector>
struct Foo {
~Foo() {
for (auto& p : *foos) {
p.data.reset();
}
}
std::shared_ptr<int> data;
std::shared_ptr<std::vector<Foo>> foos;
};
int main() {
std::shared_ptr<int> ptr;
std::cout << "use count | before: " << ptr.use_count() << '\n';
{
Foo foo;
foo.data = std::make_shared<int>(5);
foo.foos = std::make_shared<std::vector<Foo>>();
foo.foos->resize(8);
for (auto & f : *foo.foos) {
f.data = foo.data;
f.foos = foo.foos;
}
ptr = foo.data;
std::cout << "use count | inside: " << ptr.use_count() << '\n';
}
std::cout << "use count | after: " << ptr.use_count() << '\n';
}
Run Code Online (Sandbox Code Playgroud)
产生更好的输出:
use count | before: 0
use count | inside: 10
use count | after: 1
Run Code Online (Sandbox Code Playgroud)
但是人们必须手动重置这些指针似乎很奇怪.为什么std::vector还是std::shared_ptr这样做,自动在这里?这是一个错误吗?
我正在使用Visual Studio Community 2017版本15.9.5 - 感谢您的帮助!
问题是你有一个循环引用.
当foo被破坏,它减少引用计数的的shared_ptr,但那些没有达到零.
因此,即使std::shared_ptr<std::vector<Foo>>"无法访问",仍然有指针.(注意:垃圾收集器使用"辅助功能"来收集/释放指针).
打破循环的常用方法是使用std::weak_ptr.