C++ 为什么d';tor被称为';T

C++ 为什么d';tor被称为';T,c++,class,C++,Class,我试图初始化我自己的int数组的类,但运算符重载中的某些东西不起作用,因为某些原因,我的对象的d'tor在我希望它之前被调用,这使我的代码崩溃: #include "stdafx.h" #include "Array.h" int _tmain(int argc, _TCHAR* argv[]) { Array arr(6); arr[3] = 6; //code crashes here printf("%d\n", arr[0]); return 0; }

我试图初始化我自己的int数组的类,但运算符重载中的某些东西不起作用,因为某些原因,我的对象的d'tor在我希望它之前被调用,这使我的代码崩溃:

#include "stdafx.h"
#include "Array.h"

int _tmain(int argc, _TCHAR* argv[])
{
    Array arr(6);
    arr[3] = 6; //code crashes here
    printf("%d\n", arr[0]);
    return 0;
}
现在上课: 头文件:

#pragma once
#include <malloc.h>
class Array
{
public:
//ctor dtor and operator overloading
    Array(int);
    Array(int *, int);
    ~Array();
    Array operator[](int i);
//here memebers are defined
    int *arr;
    int size;
};
完成此功能后,我的对象将被d'tor删除

Array Array::operator[] (int i){
    for (int j=0; j < i; ++j)
    {
        ++(this->arr);
    }
    return *this;
}
Array数组::运算符[](int i){
对于(int j=0;jarr);
}
归还*这个;
}

因为
操作符[]
函数按值返回一个
数组
对象。这意味着,当您执行赋值
arr[3]=6
时,运算符返回该的一个副本,然后编译器从整数
6
隐式创建一个数组对象(因为它有一个匹配的构造函数),而赋值突然看起来像

arr[3] = Array(6);
在某些地方,临时数组对象(由
操作符[]
函数返回的对象,以及编译器在赋值的右侧创建的对象)必须被销毁,但到那时,多个对象都使用相同的指针
arr
。第一个临时对象被销毁,它删除指针,留下一个无效指针的所有其他对象。然后,下一个临时对象被销毁,并尝试删除现在无效的指针。砰,你撞车了

要解决这个问题,您需要做两件事。第一个是认识到
操作符[]
函数返回的类型错误,它应该返回对所包含数组元素的引用:

int& Array::operator[](size_t const i)
{
    return arr[i];
}
你需要做的第二件事是阅读

此外,为了防止编译器错误地从
int
值构造对象,您应该将构造函数标记为
显式

explicit Array(int);

主要问题

无论代码中存在其他问题,您的
操作员[]
的签名都是错误的:

Array Array::operator[] (int i){
     ...
}
这里不返回数组的元素!而是返回一个全新的数组。因此,在您的错误语句中,将构造一个新的临时数组,并在封闭表达式的末尾销毁它

试试这个。至少它不会立即崩溃:

int& Array::operator[] (int i){
    return arr[i];
}
撞车原因

不幸的是,您使用
malloc()
分配arr。不要在C++中这样做,而是使用<代码>新[]/CODE。这本身不会导致崩溃。但除此之外,您还可以在析构函数中使用
delete

它是
malloc()
/
free()
new
/
delete
new[]
/
delete[]
任何其他组合都是未定义的行为(当临时
数组被破坏时,这会导致原始代码崩溃)

请按如下方式更正此问题:

Array::Array(int g = 1) :size(g) //diplomatic value for size =1
{
    arr = new int[size];
}
Array::~Array()
{
    delete[] arr;
}
它将编译并运行:

其他严重问题

最后,更糟糕的是,原始的索引操作符返回
*this
,使其成为现有
数组的克隆。这个问题现在已经解决了。但是,如果要制作阵列的任何副本,则会遇到另一个问题:

这将导致在两个位置使用
arr
指针。gests destructed的第一个
数组将使原始
数组中使用的
arr
指针无效。对其
arr
的任何后续解引用都将是未定义的行为


这在我的在线演示中还没有解决,所以我强烈建议大家阅读一下

这些代码都没有任何意义。但是你最大的问题是你没有正确地遵循三的规则。事实上,这段代码非常棒。不是为了它的预期目的,而是作为一个例子。由于不可思议的原因,这段代码似乎结构良好,但几乎每一部分都做了一些与常见习惯用法和期望完全不同的事情。@ItayBraha
操作符[]
到底应该做什么?!它将
arr
增加几次,然后返回
*this
..@ItayBraha一个合理的实现将返回
int&
,并且不会对
arr
进行任何更改。我觉得你不知道你的实现是做什么的。说真的——这段代码有太多错误,也许你应该看看一个正确实现的数组类应该是什么样子的,然后从中学习。这比试图猜测它应该是什么样子,并根据猜测和假设编写临时代码更有价值。
Array::Array(int g = 1) :size(g) //diplomatic value for size =1
{
    arr = new int[size];
}
Array::~Array()
{
    delete[] arr;
}