2014-04-01 46 views
1

背景

我写一个networkprotocol驱动器和具有功能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初始化的std ::阵列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包=新包{header,body}; write(package);

    1.b)不得不求助于package_ptr(new package)? (记得使共享分配存储器的指针,并且在一个组块中的情况下,以节省存储器请求)

  2. Cppreference是读取:

    此外,F(shared_ptr的(新INT(42)) ,g())会导致内存泄漏 如果g抛出异常。如果使用make_shared为 ,则不存在此问题。

    为什么内存泄漏(可能int(42)g之前构造被调用,gshared_ptr之前调用被调用)?那么来自1.的替代代码会遭受这种潜在的泄漏吗?

+2

'写(STD :: make_shared (package_t {标题,正文}) );' – Cubbi

+0

@Cubbi很好!微软编译器不喜欢它,虽然:( –

+0

@Cubbi:如果'make_shared'抛出(即内存不足)会发生什么?已经构建的'package_t'被泄露? – ted

回答

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记载:

此外,如果g抛出异常,f(shared_ptr(new int(42)),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。如果gmake_shared之前被调用,并且如果抛出,内存永远不会被分配。

如果make_sharedg之前调用,如果g两罚全中,shared_ptr对象将已经创建成功了,它的破坏是因为RAII的保证

+0

'shared_pointer'必须保持,因为它经历了异步写入,并且指针用于在写入调用回调后释放标头/主体 – ted