在作用域生存期之前调用的C++析构函数



我有一个关于过早触发对象的析构函数的问题。我有一个动态分配的指针数组,指向动态分配的Word对象。数组的名称为words_。words_是另一个名为Dictionary的类的类属性。

在Dictionary类中,我有一个函数,用于访问每个Word对象并调用Word类的成员函数。

以下代码提前触发析构函数:

Word *curr_word_ptr = words_[idx]; // This line is okay, doesn't trigger destructor
Word curr_word = *curr_word_ptr; // This line triggers the destructor prematurely
curr_word.callMemberFunc();

由于第二行的原因,一旦函数的作用域结束,就会调用析构函数。

但如果我只通过数组索引访问它:

*(words_[idx]).callMemberFunc(); // The desctructor is not called prematurely

问题是因为我有一个堆栈变量(甚至不是堆栈指针变量(访问动态分配的对象吗?因此,当函数的作用域结束时,堆栈变量(curr_word(和动态分配的堆栈对象都会被破坏?

谢谢。

Word curr_word = *curr_word_ptr;定义了一个本地Word,它只存在于您的函数的本地作用域中。当函数退出时,它将被销毁。请注意,被销毁的是初始Word的副本,而不是原件。

如果你想要方便的语法,这样你就不必全部取消引用,或者复制,可以使用引用:

Word &word = *curr_word_ptr;

这是C++提供的语法糖,用来(直接(引用没有指针的对象。不过请注意,在这种情况下,对word所做的任何更改都会影响您的原始单词。

如果您的Word包含动态分配的内存,问题会更糟。假设您使用默认的复制构造函数,地址将被复制。因此,本地Word的破坏将释放仍由原始Word引用的内存,从而在下次访问时导致崩溃。

Word curr_word = *curr_word_ptr;

创建对象的堆栈上副本,该副本将被销毁。

很可能您的类缺少一个逻辑,您需要定义复制构造函数来防止崩溃,或者禁用复制构造函数,这样您就可以像这里一样错误地创建复制。

*(words_[idx]).callMemberFunc();

直接对存储在数组中的对象所指向的对象调用方法。未创建副本。

写这行的其他方式:

words_[idx]->callMemberFunc();

我也看到了一个问题,因为你使用的是原始指针。由于c++11,这种方法被认为是不好的做法。学习使用std::uniqie_ptrstd::shared_ptr

也使用std::vector代替常规C阵列

最新更新