使用make_shared初始化std :: array

时间:2014-04-01 19:20:57

标签: arrays c++11 exception-safety make-shared

背景

我正在编写网络协议的驱动程序,并且函数为write(std::shared_ptr<package> package),其中packagestd::array<buffer_ptr,2>(0 =&gt;标题,1 =&gt;正文)。为方便起见,我想编写一个函数write(buffer_ptr body),它会自动生成标题并调用write的第一种形式。为此,我希望我们std::make_shared,但是我在std::array来电中初始化make_shared时遇到了问题。

代码

typedef std::shared_ptr<std::vector<uint8_t>> buffer_ptr;
typedef std::array<buffer_ptr, 2> package_t;
typedef std::shared_ptr<package_t> package_ptr;

void connection::write(package_ptr package) {
    ... //do stuff
}

void connection::write(buffer_ptr body) {
    buffer_ptr header = buildHeader(body);
    write(std::make_shared<package_t>(???)) //here I want to initialize the array with {header,body}
}

我尝试了什么???

(这些导致编译器错误)

{header, body}
{{header, body}}
std::initializer_list<buffer_ptr>{header, body}

问题:

  1. 是否有解决方案可以完成这项工作,或者我必须写下类似的内容:

    package_ptr package = new package {header,body}; 写(包);

    1.b)我是否因为不得不诉诸package_ptr(new package)而失去效率? (我记得在一个块中为指针和实例共享内存,以节省内存请求)

  2. Cppreference上显示为:

      

    此外,f(shared_ptr(new int(42)),g())可能导致内存泄漏   如果g抛出异常。如果make_shared是,则不存在此问题   使用

    为什么会泄露内存(可以在调用int(42)之前构建g,并在调用g之前调用shared_ptr?而来自1的替代代码是否会遭受这种潜在的泄漏?

1 个答案:

答案 0 :(得分:1)

首先:

array没有明确声明构造函数。特别是,它没有一个构造函数来获取初始化列表。

我认为一种干净的方法是避免代码中的显式new并将其留给标准函数:

package_t p = {header, body};
write(std::make_shared<package_t>(p));

如果既没有new也没有std::shared_ptr,代码看起来会更好:

package_t p = {header, body};
write(p);

其次,Cppreference.com上的内容为:

  

此外,f(shared_ptr(new int(42)),g())   如果g抛出异常,可能导致内存泄漏。这个问题并不存在   如果使用make_shared则存在。

标准没有指定评估函数参数的顺序,只要表达式产生相同的结果,就可以按任何顺序计算表达式。

f(shared_ptr(new int(42)), g())

new int(42)必须在shared_ptr()之前,但不能在g()之前,如果g抛出,这可能会导致泄漏。

f(make_shared<int>(42), g())

分配发生在make_shared内。如果在g之前调用make_shared并且如果它抛出,则永远不会分配内存。

如果在make_shared之前调用g并且g抛出shared_ptr,则{{1}}对象已经创建,并且由于RAII而保证了它的销毁