c++ - 我们如何从成员函数返回一个 unique_pointer 成员?

标签 c++ pointers c++11 shared-ptr unique-ptr

我有一个带有指针成员的基类。我必须做出有根据的猜测来确定它应该是 unique_ptr 还是 shared_ptr。它们似乎都无法解决我的特定用例。

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
};

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

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 的实现可以。这种行为在标准中有详细记录

参见 12.8 §34 和 §35:

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 显式转移所有权,成员指针将来将无法使用。

或者,我必须将指针定义为 shared_ptr,但这对于 Derived2::get 的实现来说是额外的开销。

注意 应该考虑到 Derived2::get 的出现次数比 Derived1::get 多所以设计决定使用 std::shared_ptr 可以产生相当大的相对影响。

最佳答案

你的 Derived1 unique_ptr 无法按您希望的方式处理案例.您需要多个指向同一资源的智能指针。 unique_ptr根本不是一个选择。没有办法解决这个问题。

你可以坚持使用 unique_ptr成员,但让你的函数返回一个原始指针。

virtual int *get() = 0;

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

你可以使用 shared_ptr成员,正如你所建议的,并让你的函数返回它。这在您的 Derived2 中功能齐全类,但正如您所指出的,次优。

不过,它仍然是最干净的解决方案。对于只知道他们有一个 Base 的来电者,您需要某种方式来通知他们(手动或通过返回的类型)他们在完成 get() 后应该做什么的结果,所以你不能返回 unique_ptr<int>无论如何。

函数返回的唯一途径unique_ptr<int>如果调用者已经知道你有一个 Derived2 可能会有用.但是,您可以添加一个新成员:

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> 很有可能实现就足够了,在性能方面,然后可读性可能应该是添加新成员的原因。

关于c++ - 我们如何从成员函数返回一个 unique_pointer 成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28539763/

相关文章:

c++ - 需要有关跳过列表的信息

c++ - Directx11 链接器错误

c++ - 用于制作C++库的API宏

c - 这两个指针有什么区别

C++复制控制问题

c++ - 为什么不需要将具有删除的拷贝构造函数的类型的移动构造函数标记为已删除?

c++ - 如何使用 BCrypt 进行 RSA(非对称加密)

c++ - 函数原型(prototype)和数组参数

pointers - 为什么 `std::ptr::null`无法用于未定义大小的类型?

c++ - 如何使用 variadic size_t 模板将多个 std::tuple_element 分配为函数参数