简体   繁体   English

std::make_shared 和 protected/private 构造函数

[英]std::make_shared and protected/private constructors

[Edit: Turns out we don't even need reinterpret cast, making this even simpler] [编辑:原来我们甚至不需要重新解释演员表,使这更简单]

This came up here and I found a better solution using reinterpret cast and shared pointer aliasing constructor.这出现在这里,我找到了一个使用重新解释强制转换和共享指针别名构造函数的更好的解决方案。 It allows both the ctor and dtor to be private, as well as use of the final specifier.它允许 ctor 和 dtor 都是私有的,也允许使用 final 说明符。

The reputation system won't let me leave this as an answer in that question, so I had to provide it as another question...声誉系统不会让我把它作为那个问题的答案,所以我不得不把它作为另一个问题提供......

#include <iostream>
#include <memory>

class Factory final {
public:
    template<typename T, typename... A>
    static std::shared_ptr<T> make_shared(A&&... args) {
        auto ptr = std::make_shared<Type<T>>(std::forward<A>(args)...);
        return std::shared_ptr<T>(ptr, &ptr->type);
    }
private:
    template<typename T>
    struct Type final {
        template<typename... A>
        Type(A&&... args) : type(std::forward<A>(args)...) { std::cout << "Type(...) addr=" << this << "\n"; }
        ~Type() { std::cout << "~Type()\n"; }
        T type;
    };
};

class X final {
    friend struct Factory::Type<X>;  // factory access
private:
    X()      { std::cout << "X() addr=" << this << "\n"; }
    X(int i) { std::cout << "X(...) addr=" << this << " i=" << i << "\n"; }
    ~X()     { std::cout << "~X()\n"; }
};

int main() {
    auto ptr1 = Factory::make_shared<X>();
    auto ptr2 = Factory::make_shared<X>(42);
}

Giving the following output under gcc...在 gcc 下给出以下输出...

X() addr=0x62bc30                                                                                                      
Type(...) addr=0x62bc30                                                                                                    
X(...) addr=0x62bc50 i=42                                                                                              
Type(...) addr=0x62bc50                                                                                                
~Type()                                                                                                                
~X()                                                                                                                   
~Type()                                                                                                                
~X()  

Just a followup... The approach above doesn't play well with std::enable_shared_from_this<> because the initial std::shared_ptr<> is to the wrapper and not the type itself.只是后续... 上述方法与 std::enable_shared_from_this<> 效果不佳,因为初始 std::shared_ptr<> 是针对包装器而不是类型本身。 We can address this with an equivalent class that is compatible with the factory...我们可以使用与工厂兼容的等效类来解决这个问题......

#include <iostream>
#include <memory>

template<typename T>
class EnableShared {
    friend class Factory;  // member access
public:
    std::shared_ptr<T> shared_from_this() { return weak.lock(); }
protected:
    EnableShared() = default;
    virtual ~EnableShared() = default;
    EnableShared<T>& operator=(const EnableShared<T>&) { return *this; }  // no slicing
private:
    std::weak_ptr<T> weak;
};

class Factory final {
public:
    template<typename T, typename... A>
    static std::shared_ptr<T> make_shared(A&&... args) {
        auto ptr = std::make_shared<Type<T>>(std::forward<A>(args)...);
        auto alt = std::shared_ptr<T>(ptr, &ptr->type);
        assign(std::is_base_of<EnableShared<T>, T>(), alt);
        return alt;
    }
private:
    template<typename T>
    struct Type final {
        template<typename... A>
        Type(A&&... args) : type(std::forward<A>(args)...) { std::cout << "Type(...) addr=" << this << "\n"; }
        ~Type() { std::cout << "~Type()\n"; }
        T type;
    };
    template<typename T>
    static void assign(std::true_type, const std::shared_ptr<T>& ptr) {
        ptr->weak = ptr;
    }
    template<typename T>
    static void assign(std::false_type, const std::shared_ptr<T>&) {}
};

class X final : public EnableShared<X> {
    friend struct Factory::Type<X>;  // factory access
private:
    X()      { std::cout << "X() addr=" << this << "\n"; }
    X(int i) { std::cout << "X(...) addr=" << this << " i=" << i << "\n"; }
    ~X()     { std::cout << "~X()\n"; }
};

int main() {
    auto ptr1 = Factory::make_shared<X>();
    auto ptr2 = ptr1->shared_from_this();
    std::cout << "ptr1=" << ptr1.get() << "\nptr2=" << ptr2.get() << "\n";
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM