我们如何从成员函数返回unique_pointer成员? [英] How do we return a unique_pointer member from a member function?

查看:157
本文介绍了我们如何从成员函数返回unique_pointer成员?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有指针成员的基类。我必须做出有根据的猜测,以确定它应该是 unique_ptr 还是 shared_ptr

I have a base class with a pointer member. I would have to make an educated guess to determine whether it should be an unique_ptr or a shared_ptr. None of them seems to solve my particular use case.

class Base
{
public:
    Base(): pInt(std::unique_ptr<int>(new int(10))) {};
    virtual std::unique_ptr<int> get() = 0;
    //Base(): pInt(std::shared_ptr<int>(new int(10))) {}; // Alternate implementation
    //virtual std::shared_ptr<int> get() = 0; // Alternate implementation
private:
    std::unique_ptr<int> pInt;
    //std::shared_ptr<int> pInt; // Alternate implementation
};

基类已派生到 Derived1 Derived2 。前者返回 unique_ptr 成员 pInt ,后者返回本地 unique_ptr 对象。

The base class has been derived onto Derived1 and Derived2. The former returns the unique_ptr member pInt where the later returns a local unique_ptr object.

class Derived1: public Base
{
public:
    Derived1() {};
    virtual std::unique_ptr<int> get()
    {
        //return std::move(pInt);  Will compile but the ownership is lost
        return pInt;
    }
private:
    std::unique_ptr<int> pInt;
};
class Derived2: public Base
{
public:
    Derived2() {};
    virtual std::unique_ptr<int> get()
    {
        std::unique_ptr<int> pInt(new int());
        return pInt;
    }
private:
    std::unique_ptr<int> pInt;
};

Derived1 的get实现不会隐式转移所有权,因为成员指针变量不是 eXpiring 值,而 Derived2 的实现可以做到。此行为在标准文件中有详细记录

Derived1's implementation of get would not implicitly transfer the ownership as the member pointer variable is not an eXpiring value, where as the Derived2's implementation can. This behaviour is well documented in the standard

请参见12.8§34和§35:

see 12.8 §34 and §35:


当满足某些条件时,允许实现省略
类对象的复制/移动构造[...]这种
复制/移动操作的省略,称为复制省略,是
表达式是具有
相同cv-unqualified的非易失性自动对象的名称时,在具有类返回类型的函数中的
返回语句中允许使用的...类型作为函数返回类型[...]

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object [...] This elision of copy/move operations, called copy elision, is permitted [...] in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object with the same cv-unqualified type as the function return type [...]

当满足复制操作的省略标准并且要复制的
对象指定为一个左值,对
的重载分辨率,首先执行该副本的构造函数,就好像
对象是由右值指定的一样。

When the criteria for elision of a copy operation are met and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.

尽管如此,如果我通过 std :: move 明确转让所有权,则该成员指针在 未来。

Nevertheless, if I explicitly transfer the ownership via the std::move, the member pointer would be unusable in the future.

或者,我必须将指针定义为 shared_ptr ,但这对于 Derived2 :: get 的实现。

Alternatively, I would have to make the definition of the pointer as shared_ptr but that would be an extra overhead for the implementation of Derived2::get.

注意 Derived1 :: get 相比, Derived2 :: get 的出现更多,因此使用<$ c $的设计决策c> std :: shared_ptr 可以产生相当大的相对影响。

Note It should be considered that the occurrence of Derived2::get is more compared to Derived1::get so the design decision of using std:: shared_ptr can have a considerable relative impact.

推荐答案

您的 Derived1 案例无法通过 unique_ptr 。您需要多个智能指针指向同一资源。 unique_ptr 根本不是一个选择。

Your Derived1 case cannot be handled the way you want by unique_ptr. You want multiple smart pointers to the same resource. unique_ptr is simply not an option for that. There's no way around that.

您可以坚持使用 unique_ptr 成员,但使函数返回原始指针

You could stick with a unique_ptr member, but make your function return a raw pointer.

virtual int *get() = 0;

这对于您的 Derived2 类来说很麻烦,因为尚不清楚调用方是否应释放指向的内存。我建议您不要这样做。

This is troublesome for your Derived2 class, because it is not clear whether the caller should free the pointed-to memory. I recommend you do not do this.

您可以使用 shared_ptr 成员,按照您的建议,并使函数返回该值。这在您的 Derived2 类中是完全可用的,但是正如您指出的那样,它不是最优的。

You could use a shared_ptr member, as you suggested, and make your function return that. This is fully functional in your Derived2 class, but as you point out, sub-optimal.

它仍然是最干净的解决方案。对于只知道他们有 Base 的呼叫者,您需要某种方式(手动或通过返回的类型)通知他们他们在完成 get()的结果后应该执行的操作,因此无论如何您都无法返回 unique_ptr< int>

It is still the cleanest solution, though. For callers that only know they've got a Base, you need some way of informing them (either manually or through the returned type) what they should do when they're done with get()'s result, so you cannot return unique_ptr<int> anyway.

返回 unique_ptr< int> 的函数唯一有用的唯一方法是,如果调用者已经知道您拥有 Derived2 。但随后,您只需添加一个新成员即可。

The only way a function returning unique_ptr<int> could be useful is if the caller already knows you've got a Derived2. But then, you can just add a new member:

virtual shared_ptr<int> get() {
  return get_unique();
}
virtual unique_ptr<int> get_unique() {
    std::unique_ptr<int> pInt(new int());
    return pInt;
}

仅当分析显示 shared_ptr< int>但是,get()成员实际上增加了可衡量的开销。从性能角度来看,您的 shared_ptr< int> 实现很有可能是足够的,因此可读性应该是 not 不添加新成员。

I would only do that if profiling shows that the shared_ptr<int> get() member actually adds measurable overhead, though. There's a good chance that your shared_ptr<int> implementation is sufficient, performance-wise, and then readibility should probably be a reason for not adding a new member.

这篇关于我们如何从成员函数返回unique_pointer成员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆