我正在使用我以前的帖子中的此代码中的相同代码工作,但我已经做了多个更改。我的问题是我有一个动态数组,在操作员内部的copy构造器内部的 delete[]
中,我在下面的错误中获得了错误。
lab3.exe中的0x0f7063bb(ucrtbased.dll)抛出的例外
如果有此例外的处理程序,则可以安全地继续该程序。
谁能帮我理解为什么?我检查了相关的问题,但是与我看到的相关的错误不同,但我在Google搜索中没有找到结果。我在Visual Studio 2015上使用C 11。
#include "ListArray.h"
template < typename DataType >
List<DataType>::List ( int maxNumber )
{
//maxSize = MAX_LIST_SIZE; maybe???
maxSize = maxNumber;
dataItems = new DataType[maxSize];
size = maxSize - 1;
cursor = 0; // sets cursor to the first value in list
for (; cursor <= size; cursor++)
dataItems[cursor] = 1;
cursor = 0;
}
template < typename DataType >
List<DataType>::List ( const List& source )
{
*this = source; // should be handled by copy constructor
}
template < typename DataType >
List<DataType>& List<DataType>::operator= ( const List& source )
{
if (this != &source)
{
maxSize = source.maxSize;
size = source.size;
cursor = source.cursor;
delete []dataItems; // clears dataItems, weird run-time error here. Why?
dataItems = new DataType[size];
for (int count = 0; count < size; count++)
dataItems[count] = source.dataItems[count];
}
else
// do nothing, they are the same so no copy is made
return *this;
}
template < typename DataType >
List<DataType>::~List ()
{
maxSize = 0;
size = 0;
cursor = -1;
delete[] dataItems;
}
编辑:我最初发布了其他几个不完整功能,也是我要构建的程序的一部分。我的意思是只包括我所知道的正在引起的问题。我对糟糕的帖子表示歉意。
如果您要使用分配操作员制作副本,则需要一个空的对象才能开始,否则operator=
在尝试清理旧内容时会发生可怕的失败替换它们(正如Sam在他的回答中所解释的那样,Mikecat在他的评论中提到的 - 给了他们upvotes-以及迪特在您之前的问题上告诉您的)。
由于C 11,构造函数链接又称构造函数委托是可以的,因此:
template < typename DataType >
List<DataType>::List ( const List& source )
: List() /* default construct object before proceeding */
{
*this = source; // should be handled by copy constructor
}
另一个选项是使复制构造函数负责创建默认对象本身,这就是C 98和C 03中所需的内容:
template < typename DataType >
List<DataType>::List ( const List& source )
: maxSize(0), dataItems(NULL), size(0) // initialize members
{
*this = source; // should be handled by copy constructor
}
,但这正在重复默认构造函数的功能,因此,只要您的编译器支持C 11功能,就可以调用现有的功能。
构造委员会委托的细节...变得复杂。除其他外,通常从对象构造函数内部抛出的任何例外都可以防止对象存在,并且destructor均未调用。当使用委托时,当任何构造函数完成时,对象就会生存,并且包装器构造函数中的例外将面对一个已经活着的对象,并为您调用破坏者。这种行为可能是理想的,也可能不是可取的,但这是值得关注的,因为异常安全在现代C 很重要。
复制构造器不会在类的新实例中初始化任何内容。它所做的就是调用分配操作员。
分配操作员执行:
delete []dataItems;
由于dataItems
尚未初始化,因此导致不确定的行为和立即崩溃。