关于我没有得到的shared_ptr的东西
Something about shared_ptr I don't get
当我运行这段代码时:
#include <iostream>
#include <memory>
struct Adaptee {
int value = 0;
};
class Adapter {
private:
Adaptee* adaptee;
public:
Adapter (Adaptee* a) : adaptee(a) {}
void increaseValueByOne() {adaptee->value++;}
};
int main() {
Adaptee* a = new Adaptee;
Adapter* adapter = new Adapter(a);
adapter->increaseValueByOne();
delete adapter;
std::cout << "a->value = " << a->value << std::endl;
}
得到输出:a->value = 1。但是当我运行这个:
struct Adaptee {
int value = 0;
};
class Adapter {
private:
std::shared_ptr<Adaptee> adaptee;
public:
Adapter (Adaptee* a) : adaptee (std::shared_ptr<Adaptee>(a)) {}
void increaseValueByOne() {adaptee->value++;}
};
int main() {
Adaptee* a = new Adaptee;
Adapter* adapter = new Adapter(a);
adapter->increaseValueByOne();
delete adapter;
std::cout << "a->value = " << a->value << std::endl;
}
我得到:a->value = 7738248
为什么会这样?adapter->adaptee的use_count不是简单地从2更改为1,所以应该不会出错吗?当我删除'delete adapter;'这一行时,一切都很好,但是随后就有泄漏。
因为在第二种情况下,当您使用delete adapter
时,Adaptee
实例被shared_ptr
的析构函数删除,因为它是拥有该对象的最后一个shared_ptr
。
如果您希望在删除适配器后保持适配器的活动,您应该从一开始就将其包装到shared_ptr中:
class Adapter {
private:
std::shared_ptr<Adaptee> adaptee;
public:
Adapter (const std::shared_ptr<Adaptee>& a) : adaptee (a) {}
void increaseValueByOne() {adaptee->value++;}
};
int main() {
std::shared_ptr<Adaptee> a(new Adaptee);
Adapter* adapter = new Adapter(a);
adapter->increaseValueByOne();
delete adapter;
std::cout << "a->value = " << a->value << std::endl;
}
第一行
delete adapter;
对adaptee
没有任何影响。它仍然是一个有效的指针。
在第二种情况下,同一行调用shared_ptr
的析构函数,释放adaptee
所指向的内存。因此,adaptee
不是一个有效的指针,如果对它解引用,可能会出现未定义的行为。
shared_ptr
的原理是管理不再使用的指向对象的删除。
当您在适配器中创建shared_ptr
时,它获得对象的所有权并将使用计数设置为1。当适配器被删除时,共享指针也被删除。使用计数(可以使用use_count()
显示)因此自动递减并达到零。因此对象被删除,a指向一个无效的地址。
如果你不希望shared_ptr
在删除adapter
时释放a的内存,你应该创建你的原始指针为shared_pointer:
int main() {
auto a = std::make_shared<Adaptee>(); //shared pointer instead of Adaptee* a = new Adaptee;
...
}
并在Adapter类中添加一个额外的构造函数:
Adapter(std::shared_ptr<Adaptee> a) : adaptee(a) {}
对于shared_ptr
的这种一致使用,当适配器被删除时,共享指针的使用计数将变为1,并且您的代码的其余部分将像您期望的那样工作,像原始版本一样打印1。
扩展其他人所说的,当您给shared_ptr
一个原始堆分配的指针时,您给shared_ptr
对资源生命周期的控制。shared_ptr
保持一个引用计数,表示有多少shared_ptr
指向一个资源。当该计数为0
时,资源被清理。
adaptee (std::shared_ptr<Adaptee>(a))
这里引用计数是1
,因为有1
shared_ptr
指向资源a
。
delete adapter;
导致adapter
中的shared_ptr
超出作用域。调用shared_ptr
的析构函数,减少引用计数。由于引用计数现在是0
, delete
在a
上被调用。
std::cout << "a->value = " << a->value << std::endl;
这里,a不再是一个有效的指针,因为delete
在shared_ptr
的析构函数中被调用。
如果你想要a
保持有效,你应该做以下事情:
struct Adaptee {
int value = 0;
};
class Adapter {
private:
std::shared_ptr<Adaptee> adaptee;
public:
Adapter (std::shared_ptr<Adaptee> a) : adaptee(a) {}
void increaseValueByOne() {adaptee->value++;}
};
int main() {
std::shared_prt<Adaptee> a = std::make_shared<Adaptee>(); //reference count is 1
Adapter* adapter = new Adapter(a); //reference count is 2
adapter->increaseValueByOne();
delete adapter; //reference count is 1
std::cout << "a->value = " << a->value << std::endl;
} // reference count is 0; memory is deallocated
- CLANG 编译器 说:变量"PTR"可能未初始化
- 在以唯一ptr为值的C++映射中,动态内存何时会被销毁
- 将 ptr 传递给 ptr 到 A 作为参数传递给 A 的函数是不好的做法吗?
- 为共享 ptr 向量实现复制 c'tor?
- 字符和整数中 **(ptr+1) 的值差异
- C++:在不中断共享的情况下通过引用传递共享 PTR?
- 如何将派生类从基 ptr 分配给 nlohmann::json
- 引用 std::shared:ptr 以避免引用计数
- 为什么我不能在不进行任何转换的情况下将浮点数放入任何类型的 ptr 中?
- 在调用函数时,ptr** 和 ptr*& 之间是否有区别,或者首选C++?
- 另一种类型的智能ptr,比如具有弱refs的unique_ptr
- 尝试打印出 *ptr++ 的值,以了解它是如何工作的
- 如何控制共享 ptr 引用计数?
- dopen():不以 root 身份运行时"failed to map segment from shared object"
- C++中的指针否定 (!ptr == NULL)
- 从const ptr*转换为ptr*时出现问题
- 无法使用 libtool 将 -shared 参数传递给 g++
- boost::shared_ptr和std::shared-ptr的同居
- 我可以用std::shared_ptr而不是boost::shared-ptr构建boost库吗
- shared-ptr-C++shared_ptr与unique_ptr用于资源管理