我现在面临的,我有一个情况std::vector的boost::shared_ptr一个基类的秒.在我的程序过程中,我需要将共享指针存储到该向量中的派生类对象,并且稍后在程序中,需要检索这些共享指针.
以下代码说明了我的问题:
#include <iostream>
#include <vector>
using namespace std;
#include <boost/make_shared.hpp>
#include <boost/foreach.hpp>
class Base
{
public:
virtual ~Base()
{
}
};
/******************************************/
typedef boost::shared_ptr< Base > BasePtr;
/******************************************/
class Derived1 : public Base
{
public:
void derived1_test()
{
cout << "derived1_test" << endl;
}
/******************************************/
int i1;
};
/******************************************/
typedef boost::shared_ptr< Derived1 > Derived1Ptr;
/******************************************/
class Derived2 : public Base
{
public:
void derived2_test()
{
cout << "derived2_test" << endl;
}
/******************************************/
int i2;
}; …Run Code Online (Sandbox Code Playgroud) 将相同的指针发送到两个不同shared_ptr的指针是不好的,它会导致双重释放,如下所示:
int* p = new int;
std::shared_ptr<int> p1(p);
std::shared_ptr<int> p2(p); // BAD
Run Code Online (Sandbox Code Playgroud)
您可以通过以下方式实现相同目的std::enable_shared_from_this:
class Good: public std::enable_shared_from_this<Good>
{
public:
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
};
int main()
{
std::shared_ptr<Good> gp1(new Good);
std::shared_ptr<Good> gp2 = gp1->getptr();
}
Run Code Online (Sandbox Code Playgroud)
但这仍然无法防范:
class Good: public std::enable_shared_from_this<Good>
{
public:
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
};
int main()
{
Good* p = new Good;
std::shared_ptr<Good> gp3(p);
std::shared_ptr<Good> gp4(p); // BAD
}
Run Code Online (Sandbox Code Playgroud)
如果您有这样的代码,这可能会成为一个问题:
void Function(std::shared_ptr<Good> p)
{
std::cout << p.use_count() << '\n'; …Run Code Online (Sandbox Code Playgroud) 避免使用未命名的shared_ptr临时值来保存输入; 要了解为什么这是危险的,请考虑以下示例:
void f(shared_ptr<int>, int);
int g();
void ok() {
shared_ptr<int> p(new int(2));
f(p, g());
}
void bad() {
f(shared_ptr<int>(new int(2)), g());
}
Run Code Online (Sandbox Code Playgroud)
函数ok遵循字母的准则,而bad构造临时shared_ptr,承认内存泄漏的可能性.由于函数参数是以未指定的顺序计算的,因此可以首先计算new int(2),g()second,如果g抛出异常,我们可能永远不会访问shared_ptr构造函数.<...>
通过使用boost/make_shared.hpp中定义的make_shared或allocate_shared工厂函数,也可以消除上述异常安全问题.这些工厂功能还通过合并分配提供了效率优势.
我想我会开始使用make_shared,但我想知道这一点建议是否仍然适用于C++ 11 shared_ptr.我问,因为我并不完全理解为什么投掷g()会阻止ctor被调用.
Boost文档描述了共享指针在同时从多个线程访问它时的行为.特别是他们举了一些例子:
shared_ptr<int> p(new int(42));
//--- Example 1 ---
// thread A
shared_ptr<int> p2(p); // reads p
// thread B
shared_ptr<int> p3(p); // OK, multiple reads are safe
//--- Example 2 ---
// thread A
p.reset(new int(1912)); // writes p
// thread B
p2.reset(); // OK, writes p2
//--- Example 3 ---
// thread A
p = p3; // reads p3, writes p
// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write
...
Run Code Online (Sandbox Code Playgroud)
但他们没有说(或者我看不到)如果同时shared_ptr写入和读取同一个对象会发生什么.说:
shared_ptr<int> p(new int(42)); …Run Code Online (Sandbox Code Playgroud) 例如,有一个函数可以找到一个对象,如果找到了对象则返回shared_ptr,并且必须以某种方式指示没有找到对象.
std::vector<std::shared_ptr> Storage::objects;
std::shared_ptr<Object> Storage::findObject()
{
if (objects.find)
{
return objects[x];
}
else
{
return nullptr;
}
}
std::shared_ptr<Object> obj = Storage::findObject();
if (obj)
{
print("found");
}
else
{
print("not found");
}
Run Code Online (Sandbox Code Playgroud)
返回使用nullptr隐式初始化的shared_ptr是否正确?它会起作用,但可以这样做吗?或者我应该返回shared_ptr默认构造而不是?
怎么会是weak_ptr?检查空weak_ptr已被返回的正确方法是什么?by weak_ptr :: expired函数还是有其他方法吗?如果通过weak_ptr :: expired检查是唯一的方法那么我如何区分该函数返回空指针,或者对象刚被删除(多线程环境)?
对于以下代码段,它在方法中显示不同的引用计数.有人可以解释为什么这些价值不同吗?
class Foo {
};
void f1( const std::shared_ptr<Foo>& ptr ) {
std::cout << "f1(): counts: " << ptr.use_count() << std::endl;
}
void f2( const std::shared_ptr<const Foo>& ptr ) {
std::cout << "f2(): counts: " << ptr.use_count() << std::endl;
}
int main() {
std::shared_ptr<Foo> ptr( new Foo );
std::cout << "main(): counts: " << ptr.use_count() << std::endl;
f1( ptr );
f2( ptr );
std::cout << "main(): counts: " << ptr.use_count() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
相应的输出:
main(): counts: 1
f1(): …Run Code Online (Sandbox Code Playgroud) 我有一个std::shared_ptr自定义删除器和删除器,我想采取原始的临时副本std::shared_ptr.以代码形式表示:
struct Foo : public std::enable_shared_from_this<Foo>
{};
void deleter(Foo *f)
{
{
std::shared_ptr<Foo> tmp = f->shared_from_this(); // Line A
}
delete f;
}
int main()
{
std::shared_ptr<Foo> foo(new Foo, &deleter);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:在A线上,可以说一下这个电话shared_from_this()吗?这合法吗?如果是这样,标准是否对其返回值有所说明?如果我们enable_shared_from_this用不同的weak_ptr或全局的引用替换foo,那么答案是否相同?
锵用的libc ++和GCC用的libstdc ++都产生代码终止对bad_weak_ptr例外,但我似乎无法为跟踪这一要求的标准.这是特定于实现的,还是我错过了规则?
我找到的所有相关规则(引用C++ 11):
20.7.2.2.2
shared_ptr析构函数1 ...如果
*this拥有一个对象p和一个删除器d,d(p)则称为
2 [ 注意: ......由于销毁会*this减少与*this一个共享所有权的实例数量,在 …
我有2 shared_ptr秒定义和分配nullptr.在案例1中,我使用默认构造函数,在案例2中,我使用了构造函数和delete方法.
shared_ptr<int> sptr2(nullptr);
cout << "sptr2 use_count: " << sptr2.use_count() << endl;
shared_ptr<int> sptr6(nullptr, default_delete<int>());
cout << "sptr6 use_count: " << sptr6.use_count() << endl;
Run Code Online (Sandbox Code Playgroud)
输出是:
sptr2 use_count: 0
sptr6 use_count: 1
Run Code Online (Sandbox Code Playgroud)
我不明白为什么sptr6在没有任何有效指针时使用count为1.
g ++(GCC)4.8.5 20150623(Red Hat 4.8.5-16)
鉴于在 for 循环的条件子句中声明的 shared_ptr 变量包含 if/continue 语句,Microsoft 编译器(自 2015 版起)每次循环迭代都会生成额外的析构函数调用(总共两个)。这会导致 Holder 界面用户无法访问的 Item 对象被破坏。请参阅下面的示例代码
namespace
{
class Item
{
public:
Item(size_t v)
: value_(v)
{
std::cout << "Item(" << value_ << ")" << std::endl;
}
~Item()
{
std::cout << "~Item(" << value_ << ")" << std::endl;
}
void print() const
{
std::cout << "Item::print(" << value_ << ")" << std::endl;
}
private:
size_t value_;
};
typedef std::shared_ptr<const Item> ItemCPtr;
class Holder
{
public:
Holder(size_t n)
{
for (size_t i = …Run Code Online (Sandbox Code Playgroud) std::make_shared_for_overwrite()C++20除了以下之外还引入了新函数std::make_shared():
https: //en.cppreference.com/w/cpp/memory/shared_ptr/make_shared
为什么旧make_shared功能不够用,什么情况下需要使用新功能?
c++ ×10
shared-ptr ×10
c++11 ×4
weak-ptr ×2
c++20 ×1
destructor ×1
inheritance ×1
pointers ×1
std ×1
templates ×1
visual-c++ ×1