我知道这是一个常见错误,所以我尝试创建一个最小的例子。我认为这是因为我试图释放堆栈内存,但我不太明白我可以做些不同的事情。
Maze.h
#pragma once
class Maze
{
public:
Maze();
Maze(unsigned int height, unsigned int width);
~Maze();
private:
unsigned int m_height;
unsigned int m_width;
char *entrance;
char *exit;
char *m_cells;
};
Maze.cpp
#include "Maze.h"
using namespace std;
Maze::Maze()
{
}
Maze::Maze(unsigned int height, unsigned int width) :
m_height(height),
m_width(width)
{
m_cells = new char[m_height * m_width];
entrance = nullptr;
exit = nullptr;
}
Maze::~Maze()
{
delete entrance;
delete exit;
delete[] m_cells; //this line causes the error
}
导致错误的main.cpp
#include <iostream>
#include <string>
#include "Maze.h"
using namespace std;
int __cdecl main(int argc, char **argv)
{
Maze maze;
maze = Maze(10, 10);
}
main.cpp没有错误
#include <iostream>
#include <string>
#include "Maze.h"
using namespace std;
int __cdecl main(int argc, char **argv)
{
Maze maze(10, 10);
}
2个电源有什么区别?为什么第一个导致错误?这是一个问题,因为我想声明迷宫,但稍后在我的程序中初始化它。在这里,我只用两行来创建一个最小的例子。
当程序关闭时发生错误,所以我认为这是一个内存释放问题。的确,当我删除 delete [] m_cells; 来自析构函数,不再出错。
这里到底发生了什么?
答案 0 :(得分:2)
该行:
maze = Maze(10, 10);
正在创建对象的副本,所以会发生什么:
Maze(10, 10)
- 构建一个新对象,使用operator new
和operator new[]
分配内存。要解决有关规则3的读数,您需要添加复制构造函数和赋值运算符。
例如:
// This the copy constructor
Maze::Maze(const Maze& other)
{
// Call the assignment operator, saves duplicating the assignment operator code in here.
*this = other;
}
// This is the assignment operator
Maze& Maze::operator = ( const Maze& other )
{
if ( this != &other )
{
// TODO: Copy your pointers, not by assigning them, but use operator new and copy the data as "other" will destruct and delete those pointers, hence your problem
}
return *this;
}
如果您使用的是C ++ 11,您也可以使用移动构造/赋值,然后只需交换指针,并将源对象指针设置为NULL / nullptr。
在C ++ 11中,您还可以使用default和delete关键字来防止使用您不应该调用的构造函数,例如:
class Foo
{
public:
Foo() = default;
// Prevent copying
Foo(const Foo&) = delete;
Foo& operator = ( const Foo& ) = delete;
int x = 0;
};
这会导致以下内容在编译阶段失败:
Foo a;
a = Foo();