在C ++ 11中将结构作为输出参数传递

时间:2015-01-24 03:21:51

标签: c++ c++11 struct shared-ptr unique-ptr

在C ++ 11中将结构作为输出传递的最佳做法是什么?

是否应在外部函数中创建结构,或者在外部函数维护所有权时创建内部结构?

而且,它应该是shared_ptr还是unique_ptr?

例如,假设我有一个复杂的结构:

struct Error {
    string Code;
    string Message;
    string Details;
    string Command;
};

struct Response {
    stringstream Data;
    bool Success;
    Error Error;
};

然后,从调用函数,我想说:

Response r;
getResponse( url, &r );

getResponse应定义为:

getResponse( string, shared_ptr );    or
getResponse( string, unique_ptr );

另外,如何声明字符串和字符串流?他们也应该是shared_ptr吗?

在这种情况下,getResponse函数在完成后不希望与响应有任何关系,并且响应本身的生命周期应由调用者决定。

声明和填充结构的最佳做法是什么?

4 个答案:

答案 0 :(得分:8)

现代编译器非常擅长优化函数返回值的方式,因此通常在有意义时按值返回:

// Just return by value
Response getResponse(const std::string& url)
{
    Response r;

    // ...

    return r;
}

答案 1 :(得分:1)

好的,基于我无法复制数据的事实,在我的情况下,返回类型的响应将不起作用。

似乎我有两个选择:

int getResponse( const std::string &url, shared_ptr<Response> )

unique_ptr<Response> getResponse( const std::string &url )

所以它变成了代码:

if( !getResponse( "http://...", response ) )
   // report error

而不是

if( getResponse( "http://..." ) == nullptr )
   // report error

在编码模式/最佳实践方面,哪个更好?

我与第二个的优点是,我可以检查结果而无需查看nullptr。

答案 2 :(得分:0)

首先,Galik的答案是正确的,只是按价值回归。那么你的方法显然都是错误。堆栈中有一个对象,该对象的生命周期完全由编译器管理,您不能delete该对象(或使用指向delete的智能指针)。

如果你对不按值返回有一些特别的兴趣(也许对象在紧密的循环中被重用,你希望重用字符串缓冲区......很可能不是这种情况,但请耐心等待我),我会建议您使用引用作为参数或指针

void getResponse(std::string const& url, Response& resp);
void getResponse(std::string const& url, Response* resp);

第一个更清楚,第二个参数不是可选的,并且不需要测试或担心它可能为空。另一方面,某些编码约定需要第二种形式,因为从调用者方面可能更清楚该函数将修改对象(在调用getResponse(url, &response)url参数获胜&# 39; t被修改,response可能(&)。这就是谷歌编码风格的例子。我个人更喜欢参考,但你知道......在罗马时......如果你的商店有一个政策就跟着它。

答案 3 :(得分:0)

为什么你应该在这里按值返回一个稍微不同的答案是你的结构的内容。如果对象的内容移动便宜,那么您应该按值返回。移动语义将自动启动,因为编译器知道您要返回的本地范围对象即将被销毁。

如果你的对象不便宜移动/复制,我说通过ref / pointer的经典建议仍然适用。 unique_ptr / shared_ptr只应在解决对象所有权时发挥作用。即。我将此对象传递给函数,该函数现在拥有它。如果所有权未被更改,请使用传递给ref和指针的经典建议。