首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >工厂返回智能指针的C++寿命

工厂返回智能指针的C++寿命
EN

Stack Overflow用户
提问于 2015-11-07 14:13:21
回答 2查看 623关注 0票数 0

我在C++11中使用一个工厂模式,它位于我的main()函数的范围内,调用如下所示:

代码语言:javascript
复制
histogram_requests -> AddNewPostfix( Postfix_factory :: get_postfix( "Layers", ntuple_reader ) );

Postfix_factory::get_postfix()是一个静态成员函数,返回一个std ::unique_ptr< Postfix>。一个示例返回值是:

代码语言:javascript
复制
return std :: move( std :: unique_ptr<Postfix>( new Layers_postfix( ntuple_reader_p ) ));

我的第一个问题是这样做是否有效?返回的指针是否在我的main()作用域的末尾被销毁了?

第二件事是,我想把这个指针传递给一个函数。正确的做法是什么?当我将AddNewPostFix()的参数类型设置为std::unique_ptrstd::unique_ptr&&但作为简单引用失败时,我的程序就会编译。我不想让我的AddNewPostFix()不小心删除指针中的数据,但我不确定这些数据是否安全。有人能告诉我如何正确和安全地做这件事吗?

EN

回答 2

Stack Overflow用户

发布于 2015-11-07 15:26:19

返回std ::move( std ::unique_ptr(新Layers_postfix( ntuple_reader_p );

这里有两件事值得注意:

  1. 语句。
  2. 您应该使用std::make_unique。它只有在C++14之后才得到官方支持,但不管怎么说,您的编译器都支持它,或者您可以轻松地创建自己的版本。

返回的指针是否在我的main()作用域结束时被销毁?

“返回的指针”可以引用以下几个内容。

当然,std::unique_ptr对象被销毁了。当所有本地对象的作用域结束时,它们都会被销毁。std::unique_ptr内部的原始指针数据成员也被销毁,但这是微不足道的。

我认为您真正的意思是指向并由std::unique_ptr管理的对象,即动态分配的Postfix。该对象也将被销毁,是的,因为当std::unique_ptr结束时,main不会移动到任何地方。

如果Postfix不被销毁,那么您就会有一个内存泄漏,而std::unique_ptr将是非常无用的,不是吗?

第二件事是,我想把这个指针传递给一个函数。正确的做法是什么?

这个问题太宽泛了。赫伯·萨特曾经写过关于传递智能指针到函数的整篇文章。这是一篇很长的文章,也有有趣的用户评论。你绝对应该读一读。以下是萨特的指导方针:

不要将智能指针作为函数参数传递,除非您希望使用或操作智能指针本身,例如共享或传输所有权。

更喜欢按值、*或&,而不是通过智能指针传递对象。

使用unique_ptr参数表示“接收器”函数。

只使用非const unique_ptr&参数来修改unique_ptr

不要使用const unique_ptr&作为参数,而是使用widget*

表示函数将使用shared_ptr参数存储和共享堆对象的所有权。

只使用非const shared_ptr&参数来修改shared_ptr。只有当您不确定是否会获得副本和共享所有权时,才使用const shared_ptr&作为参数;否则使用widget* (如果不是可空的话,则使用widget&)。

我不想让我的AddNewPostFix()不小心删除指针中的数据,但我不确定这些数据是否安全。

最安全的方法不是传递指针,而是传递Postfix&Postfix const&。当然,人们仍然可以尝试delete &postfix或采用类似的不良做法。但正如俗话说的那样,C++保护的是墨菲,而不是马基雅维利。

下面是一个完整的例子:

代码语言:javascript
复制
#include <memory>
#include <string>
#include <iostream>

struct Postfix
{
    std::string layers;
    int ntuple_reader;

    Postfix(std::string const& layers, int ntuple_reader) :
        layers(layers),
        ntuple_reader(ntuple_reader)
    {
    }

    ~Postfix()
    {
        std::cout << "dtr\n";
    }
};

std::unique_ptr<Postfix> get_postfix(std::string const& layers, int ntuple_reader)
{
    return std::make_unique<Postfix>(layers, ntuple_reader);
}

void AddNewPostfix(Postfix const& postfix)
{
    std::cout << "AddNewPostfix\n";
    // do something with postfix.layers and postfix.ntuple_reader
}

int main()
{
    int ntuple_reader = 123;
    auto postfix_ptr = get_postfix("Layers", ntuple_reader);
    AddNewPostfix(*postfix_ptr);
}

正如您在输出中看到的,在Postfix的末尾正确地调用了main的析构函数。

票数 2
EN

Stack Overflow用户

发布于 2015-11-07 14:21:09

返回智能指针是可以的,直到您决定需要将其保存在不同类型的智能指针中。我只需返回一个原始指针,并让调用方决定它要使用它做什么。在您的例子中,std::move是不必要的。

若要将其传递给函数,请将函数参数设为const &并在智能指针上使用dereference操作符。

代码语言:javascript
复制
void someFunction(const T& t)
{
}

std::unique_ptr<T> t = ...;
SomeFunction(*t);
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33583702

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档