C++ 使用自己的模板化owner_ptr类分配多维数组

C++ 使用自己的模板化owner_ptr类分配多维数组,c++,pointers,memory-management,type-conversion,c++98,C++,Pointers,Memory Management,Type Conversion,C++98,编辑:我发现我的问题包含一个悖论。我在代码中使用了扩展初始值设定项列表,它是在C++11中引入的,但我只想使用C++98工具。抱歉,我太晚才注意到编译器的警告消息。当然,移动语义可以解决我在C++11中的问题。我的问题不再重要。 我决定创建一个自己的owner\u ptr类。概念是所有者\u ptr对象对动态分配的对象拥有所有权。超过1个所有者\u ptr不得拥有同一对象。以下是我的实现: #include <cstddef> template <typename T>

编辑:我发现我的问题包含一个悖论。我在代码中使用了扩展初始值设定项列表,它是在C++11中引入的,但我只想使用C++98工具。抱歉,我太晚才注意到编译器的警告消息。当然,移动语义可以解决我在C++11中的问题。我的问题不再重要。

我决定创建一个自己的
owner\u ptr
类。概念是
所有者\u ptr
对象对动态分配的对象拥有所有权。超过1个
所有者\u ptr
不得拥有同一对象。以下是我的实现:

#include <cstddef>

template <typename T>
class owner_ptr
{
    T* ptr;
    bool array;

public:
    owner_ptr() : ptr(NULL) {} /* LINE 10 */
    owner_ptr(T* ptr, bool isArray = false) : ptr(ptr), array(isArray) {} /* LINE 11 */
    owner_ptr(owner_ptr<T>& orig) : ptr(orig.ptr), array(orig.array) /* LINE 12 */
    {
        orig.ptr = NULL;
    }

    ~owner_ptr()
    {
        if (ptr != NULL)
        {
            if (!array)
            {
                delete ptr;
            }
            else
            {
                delete[] ptr;
            }
        }
    }

    owner_ptr& operator=(owner_ptr<T>& rvalue)
    {
        if (this != &rvalue)
        {
            this->~owner_ptr();
            ptr = rvalue.ptr;
            array = rvalue.array;
            rvalue.ptr = NULL;
        }
        return *this;
    }

    void reset()
    {
        this->~owner_ptr();
        ptr = NULL;
    }

    void addPtr(T* newPtr, bool isArray = false)
    {
        this->~owner_ptr();
        ptr = newPtr;
        array = isArray;
    }

    T& operator*() { return *ptr; }
    const T& operator*() const { return *ptr; }

    T* get() { return ptr; }
    const T* get() const { return ptr; }

    T* operator->() { return ptr; }
    const T* operator->() const { return ptr; }

    T& operator[](int i) { return ptr[i]; }
    const T& operator[](int i) const { return ptr[i]; }
};
它适用于一维数组。但是,当我尝试分配二维数组时,以下代码无法编译:

int main()
{
    owner_ptr< owner_ptr<int> > test(new owner_ptr<int>[2]{ owner_ptr<int>(new int[5], true), owner_ptr<int>(new int[8], true) }, true); /* LINE 72 */

    return 0;
}
然而,我很好奇,是否可以用一个命令来完成它

注意:我这样做是为了学习。这不是生产代码。因此,请不要建议我使用C++11智能指针。

我指定用户有责任创建合法所有者\u ptr对象,如:

owner_ptr<int> op1(new int);
owner_ptr<int> op2(new int[3], true);
owner_ptr<int> op3(op1);
owner_ptr<int> op4;
op4 = op3;
owner_ptr<int> op1(new int);
owner_ptr<int> op2(new int[3], true);
owner_ptr<int> op3(op1);
owner_ptr<int> op4;
op4 = op3;
owner\u ptr op1(新int);
所有者_ptrop2(新整数[3],正确);
业主ptr op3(op1);
业主(op4);
op4=op3;
那是个相当糟糕的主意。理想情况下,如果您有一个
T
T[]
数组,那么您的
owner\u ptr
类应该能够从类型中自动推断出来

IIRC我这样做是为了一些生产代码,只需将
std::auto_ptr
的一个完整专门化重写为
std::auto_array
,并向用户明确说明这一点。
这与您尝试制作
owner\u ptr
修复正确的
new
delete
调用以接受
owner\u ptr
非常相似

应用了C++98限制(无
type\u traits
support),这似乎是最简单的方法。您只需将代码替换为
new
需要
new[]
delete
需要
delete[]

我指定用户有责任创建合法所有者\u ptr对象,如:

owner_ptr<int> op1(new int);
owner_ptr<int> op2(new int[3], true);
owner_ptr<int> op3(op1);
owner_ptr<int> op4;
op4 = op3;
owner_ptr<int> op1(new int);
owner_ptr<int> op2(new int[3], true);
owner_ptr<int> op3(op1);
owner_ptr<int> op4;
op4 = op3;
owner\u ptr op1(新int);
所有者_ptrop2(新整数[3],正确);
业主ptr op3(op1);
业主(op4);
op4=op3;
那是个相当糟糕的主意。理想情况下,如果您有一个
T
T[]
数组,那么您的
owner\u ptr
类应该能够从类型中自动推断出来

IIRC我这样做是为了一些生产代码,只需将
std::auto_ptr
的一个完整专门化重写为
std::auto_array
,并向用户明确说明这一点。
这与您尝试制作
owner\u ptr
修复正确的
new
delete
调用以接受
owner\u ptr
非常相似

应用了C++98限制(无
type\u traits
support),这似乎是最简单的方法。您只需将代码替换为
new
需要
new[]
delete
需要
delete[]

与为指针或数组类型传递指示符相比,通常更好、更灵活的解决方案是让用户在构造函数中提供一个deleter函数:

template<typename T>
class owner_ptr {
    static void DefaultDeleter(T* p) {
        delete p;
    }
public:
    typedef void(*DeleterFunc)(T*);

    static void ArrayDeleter(T* p) {
        delete[] p;
    }
    owner_ptr(T* ptr, DeleterFunc = DefaultDeleter);
};
模板
类所有者{
静态无效默认删除器(T*p){
删除p;
}
公众:
typedef void(*DeleterFunc)(T*);
静态空隙阵列删除器(T*p){
删除[]p;
}
所有者(T*ptr,DeleterFunc=DefaultDeleter);
};
这样就可以用了

owner_ptr<int> op1(new int());
owner_ptr<int> op2(new int[10],owner_ptr<int>::ArrayDeleter);
owner_ptr op1(新int());
owner_ptr op2(新整数[10],owner_ptr::ArrayDeleter);
并为应该调用的任何自定义删除程序函数提供了更大的灵活性

与为指针或数组类型传递指示符相比,通常更好、更灵活的解决方案是让用户在构造函数中提供一个deleter函数:

template<typename T>
class owner_ptr {
    static void DefaultDeleter(T* p) {
        delete p;
    }
public:
    typedef void(*DeleterFunc)(T*);

    static void ArrayDeleter(T* p) {
        delete[] p;
    }
    owner_ptr(T* ptr, DeleterFunc = DefaultDeleter);
};
模板
类所有者{
静态无效默认删除器(T*p){
删除p;
}
公众:
typedef void(*DeleterFunc)(T*);
静态空隙阵列删除器(T*p){
删除[]p;
}
所有者(T*ptr,DeleterFunc=DefaultDeleter);
};
这样就可以用了

owner_ptr<int> op1(new int());
owner_ptr<int> op2(new int[10],owner_ptr<int>::ArrayDeleter);
owner_ptr op1(新int());
owner_ptr op2(新整数[10],owner_ptr::ArrayDeleter);

并为任何应该调用的自定义删除函数提供了更大的灵活性。

我不建议使用C++11智能指针,但我建议研究它们,至少在它们的接口上
isArray
参数对于初学者来说是一种暴行。另外,与第二个要点有关:出于学习的目的,没有理由使用C++98…我不建议使用C++11智能指针,但我建议研究它们,至少在它们的接口上
isArray
parameter对于初学者来说是一种暴行。另外,与第二个bullet相关:出于学习目的,没有理由使用C++98来执行此操作……抱歉,但我不清楚这是如何回答我的问题的。@GergelyTomcsányi您犯了一个小错误:
新所有者\u ptr[2]
你的意思是
新主人\u ptr
。你错了
owner\u ptr
存储
owner\u ptr
对象,而不是
owner\u ptr
对象,因此
owner\u ptr
是错误的。无论如何,我的问题不再重要。是扩展的初始值设定项列表导致了这个问题,这是一个C++11工具。我发现太晚了,因为我只想在代码中使用C++98工具(目前)。右值引用、移动语义和移动构造函数很容易解决我的问题。扩展初始值设定项列表想要调用复制构造函数(我起初不知道),但我只有一个
owner\u ptr(owner\u ptr&)
copy构造函数。问题是,我不能通过非常量引用(通过