正在构造函数内部初始化对象,而不在初始化列表中
Initializing an object inside the constructor and not in initialization list
我有一个包含3种数据类型的类:
class CentralBank{
MaxHeap richestBanks;
HashTable banks;
AccountTree accounts;
public:
CentralBank(int numAccounts, Account* accounts, int numBanks, Bank* bankArr);
void AddAccount(Account account);
void RemoveAccount(int accountID);
void AddBank(Bank bank);
int GetAccountsNumber(int bankID);
void GetKRichestBanks(unsigned int K, Bank* banks);
int GetSumBalance (int low, int high);
};
这是构造函数:
CentralBank::CentralBank(int numAccounts, Account* accounts, int numBanks,
Bank* bankArr): accounts(numAccounts,accounts){
int** locs = new int*[numBanks];
richestBanks = MaxHeap(numBanks,bankArr, locs);
banks = HashTable(numBanks,bankArr,locs);
delete[] locs;
}
我的问题是堆和哈希表的析构函数是在它们的构造函数之后调用的。如果我把它们都变成指针,那就不会发生。为什么会发生这种情况?有没有办法让它们不成为指针,也不在初始化后立即调用析构函数?我没有正确初始化它们吗?
PS:它们不在初始化列表中,因为它们的构造函数需要"locs"参数,该参数需要初始化。
一旦输入构造函数的主体,C++的规则就保证该类的所有基类和该类的全部成员都已初始化。这就是为什么初始化列表在构造函数的主体之外;因为它在构造函数主体之前被调用。如果您没有在构造函数的初始化列表中指定构造函数和参数,那么它将被默认初始化。
因此CCD_ 1和CCD_。并且您不能初始化对象两次。
richestBanks = MaxHeap(numBanks,bankArr, locs);
这样做的目的是临时创建一个新的MaxHeap
对象,然后调用复制分配运算符(或移动分配,如果适用(将新数据复制到richestBanks
中。在此之后,必须销毁临时对象。这就是你看到的析构函数调用。
正确的解决方案是停止执行任何需要locs
的操作,并找到一种更好的方法来构造数据,以便正确使用初始化列表。
richestBanks = MaxHeap(numBanks,bankArr, locs)
我记得,这意味着创建一个临时对象,运行复制构造函数将其复制到richestBanks变量,然后销毁这个临时变量。
更好的解决方案是引用对象(MaxHeap&(,而不是对象本身或指针。
我的问题是堆和哈希表的析构函数是在它们的构造函数之后立即调用的
正在为在CentralBank构造函数的主体中构造的MaxHeap和HashTable的临时实例调用析构函数,这些实例最终超出了作用域。这些临时变量被复制到成员变量richestBanks
和banks
中,这两个变量在进入该构造函数的主体时已被初始化。
假设您确实需要int指针数组,那么您可以根据正常的RAII准则设置一个辅助类来处理它的生存期。类似这样的东西:
class IntPointerArray
{
public:
IntPointerArray( int num )
: array_(new int*[num])
{}
~IntPointerArray()
{ delete [] array_; }
operator int** ()
{ return array_; }
private:
int** array_;
};
现在,扩展您的类以将其实例作为成员:
class CentralBank{
IntPointerArray locs;
MaxHeap richestBanks;
HashTable banks;
AccountTree accounts;
// rest omitted
根据成员按照声明的顺序初始化的规则,您的构造函数现在可以如下所示:
CentralBank::CentralBank(int numAccounts, Account* accounts, int numBanks, Bank* bankArr)
: locs(numBanks)
, richestBanks(numBanks,bankArr, locs) // exploits operator int**
, banks(numBanks,bankArr, locs) // ditto
, accounts(numAccounts,accounts)
{}
通过这种方式,所有成员都被直接初始化,并且根本不需要具有临时性的构造函数体。
是否应该使用这样的外部数组也值得研究。我猜你真的需要被称为treap的数据结构。
- C++类 - 初始化列表 - 递归 - 按值传递
- 在初始化列表之外手动调用基类的构造函数
- C++:带有大括号初始化列表的函数调用表达式 - 标准是否规定在单个元素列表的微不足道的情况下忽略大括号?
- std::map与谓词与初始化列表
- 类内初始化与构造函数初始化列表的顺序
- 当返回语句时,逗号运算符、大括号初始化列表和 std::unique_ptr 组合在一起
- 使用初始化列表填充C++中的多维结构数组时出现问题
- 如何在初始化列表中的构造函数之后初始化变量/对象?
- C++初始化列表与分配值
- C++初始化列表中的向量集大小或调整大小
- 在构造函数初始化列表中使用 std::variant
- emplace_back初始化列表错误,当初始化列表在独立变量上工作时
- 解释了构造函数成员初始化列表
- 使用初始化列表时如何获取私有数据?
- 用初始化列表和超类构造函数声明子类构造函数的正确方式
- 如何在成员初始化列表中声明共享指针
- 庞大的初始化列表,如何修复"fatal error C1060: compiler is out of heap space"
- 我可以检查初始化列表中设置的构造函数主体中的变量吗
- 使用整数初始化列表初始化长双精度的向量
- 是否可以在C++中使用初始化列表设置数组的特定成员?