繁体   English   中英

C ++中的数组类成员初始化

[英]Array class member initialization in C++

我有以下代码片段:

#include <iostream>
using namespace std;
class A {
    int* data;
    int size;
public:
    A(int s):size(s)
    {
        data = new int[size];
    }
    A() {
        data = nullptr;
    }
    ~A() {
        if (data) delete [] data;
    }
};
class B {
    A a[2];
public:
    B() {
        a[0] = A(10);
        a[1] = A(11); 
    }
};
int main(int argc, char *argv[]) {
    B b;
}

在上面的C ++代码中,我有一个类A ,它有一个数组成员int* data ,内存的(de)分配由(de)构造函数处理。 我创建了B类 ,它有一个固定长度的A类 数组作为数据成员。

我的问题是:如何优雅地初始化成员A a[2] 在上面的代码中, A(10)A(11)是在堆栈上创建的,当跳出作用域时,它们的析构函数将被调用,因此数据无效。 当跳转main函数的作用域时, a[2]持有的指针将被释放两次,导致错误:

pointer being freed was not allocated

一种可能的解决方案是仔细设计copy constructormove constructor ,通过这样做,上述编码范例可以工作。

我尝试过的另一个解决方案是在class B初始化列表中初始化数组:

B() : a { A(10), A(11) }

这个解决方案有效,我并没有真正告诉初始化列表的基本机制。 我认为它必须与简单的构造复制完全不同。 我真的希望有些专家能够详细解释这种机制。 当然,这种解决方案难以编码且不灵活。

所以我想知道C ++中是否有一些编程范例可以解决这个设计问题?

在上面的代码中,在堆栈上创建A(10)和A(11)

它们是临时对象。 它不指定或创建它们在那里 ,如果他们在所有创建。

当跳出范围时,他们的析构函数将被调用

在相应的移动赋值语句结束后,将调用每个临时的析构函数。

一种可能的解决方案是仔细设计复制构造函数和移动构造函数,通过这样做,上述编码范例可以工作。

并且{copy,move}赋值运算符也是如此。 当隐式声明的那些做不正确时,你应该总是这样做。 如果你在析构函数中删除了某些内容,他们就永远不会做正确的事情。

我尝试过的另一个解决方案是在B类的初始化列表中初始化数组

这个解决方案有效,我并没有真正告诉初始化列表的基本机制。 我认为它必须与简单的构造和复制完全不同。

原始代码中的错误是A移动赋值运算符。 由于初始化列表永远不会从临时移动分配,因此它永远不会触发错误。

这实际上是构建更优雅的方式a是你自找的。 不是因为它避免了这个错误,而是因为避免不必要的移动本质上是好事。

所以我想知道C ++中是否有一些编程范例可以解决这个设计问题?

是。 RAII单一责任原则 除非你的类什么也不做,除了管理data指向的内存之外,它不应该管理内存。 相反,它应该将内存管理委托给RAII对象。 在这种情况下,您应该使用std::vector成员。

class A {
    std::vector<int> data;
public:
    A(int s):data(s) {}
    A() = default;
};

使用初始化列表构造B :: a,如下所示:

class B {
    A a[2];
public:
    B() : a({10, 11}){
    }
};

理想的答案是强制A使用移动而不是副本,或者在副本上为项目分配新空间。 在这两者中,效率最高的是前者,因此我将在下面进行扩展:

强制运动可以两种方式完成:

  • 删除复制构造函数并复制operator= ,并实现自己的移动构造函数和operator=
  • 一直使用std::movestd::swap

其中,前者是优越的,因为你将不会意外地复制课程,但对于后者,你正在移动的事实将更加明显。

删除默认复制方法:

class A {
    A( const A& a ) = delete;
    A& operator =( const A& a ) = delete;
}

暂无
暂无

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

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