【问题标题】:Initialize std::array with make_shared用 make_shared 初始化 std::array
【发布时间】:2014-04-01 19:20:56
【问题描述】:

背景

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

代码

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 是,则此问题不存在 用过。

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

【问题讨论】:

  • write(std::make_shared&lt;package_t&gt;( package_t{header, body} ));
  • @Cubbi 不错!微软编译器虽然不喜欢它:(
  • @Cubbi:如果make_shared 抛出(即内存不足)会发生什么?已经构建好的package_t会泄露吗?
  • @ted 不,它会调用它的两个成员的析构函数。
  • @Cubbi 什么将调用它的两个成员的析构函数? package_t?您是否介意指出我与 2.) 中的示例的不同之处,根据 cpp 参考,这显然不起作用?

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


【解决方案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 内部。如果在make_shared 之前调用g 并且如果它抛出,则永远不会分配内存。

如果在g 之前调用make_shared 并且如果g 抛出,则shared_ptr 对象将已经创建并且由于RAII 而保证其销毁

【讨论】:

  • shared_pointer 必须保留,因为它经过异步写入,并且指针用于在写入调用回调后释放 header/body
猜你喜欢
  • 2020-01-27
  • 1970-01-01
  • 2015-10-05
  • 2012-02-10
  • 2021-03-19
  • 2017-04-17
  • 1970-01-01
  • 1970-01-01
  • 2023-02-06
相关资源
最近更新 更多