异常安全 C++ 共享指针

Posted

技术标签:

【中文标题】异常安全 C++ 共享指针【英文标题】:Exception safety C++ shared pointer 【发布时间】:2013-09-06 14:57:56 【问题描述】:

我尝试在 C++ 中实现 JSON 框架,并希望利用多态概念。我有一个类JSONNode,它是一种存储其他 JSONNode 对象本身的容器,依此类推。我正在使用指针和动态分配来做到这一点。为了异常安全,我不想使用new/delete,而是使用 boost 共享指针。将元素(进一步的 json 对象)添加到 json 对象的基本场景如下所示:

typedef boost::shared_ptr<JSONNode> JSONNodePtr;   

void JSONNode::Add(JSONNodePtr nodePtr, const std::string& name)

    this->elements[name] = nodePtr;  // store in STL std::map


// create and add json object 
JSONNodePtr obj(new JSONNode());
JSONNodePtr element(new JSONNode());
obj->Add(element, "firstElement");

为了更方便使用,我宁愿不显式分配element,并将共享指针的创建放入类方法Add

void JSONNode::Add(JSONNode* node, const std::string& name)

    JSONNodePtr nodePtr(node);
    this->elements[name] = nodePtr;


// create and add json object 
...
obj->Add(new JSONNode, "firstElement");    

但这仍然是异常安全的吗?我猜不是因为共享指针的创建不是通过 JSONNode* 的分配立即完成的。你怎么看?或者还有其他更常见的实现方式吗?

【问题讨论】:

参见make_shared 了解另一种确保异常安全的“常用方法”。 【参考方案1】:

但这仍然是异常安全的吗?

没有。如果string 的构造作为另一个参数传递给Add 抛出,则动态对象可能会泄漏。未指定首先创建哪个参数。

原始代码确保在其他任何事情发生之前将动态对象分配给智能指针:唯一可能失败的是智能指针本身的创建,在这种情况下它将删除对象。

或者还有其他更常见的实现方式吗?

通常最好使用make_shared 函数模板,而不是自己使用new。它不仅通过不暴露裸指针来保证异常安全,还通过在单个内存块中创建受控对象和共享引用计数来更有效地使用内存。

obj->Add(boost::make_shared<JSONNode>(), "firstElement"); // or std:: in C++11

【讨论】:

好的。如果我将字符串参数“name”更改为由值给出,那么函数调用中涉及复制构造函数的内容 - 由于复制构造函数可能会失败,这会改变事情吗? @MichiMichbeck:实际上,我的回答是错误的:我没有注意到你正在创建一个字符串。

以上是关于异常安全 C++ 共享指针的主要内容,如果未能解决你的问题,请参考以下文章

C++异常机制和智能指针机制的杂谈

图解shared_ptr共享智能指针原理分析

通过线程共享指针的 std::vector

C++ 中的智能指针-基础

为啥 C++ 共享指针的行为不像迭代器的标准指针?

C++ 自动指针 共享指针