我无法理解如何使用构造函数进行动态分配。
我在我的代码中使用了一个名为graph的类(它只是一个表示节点之间边缘的bool 2-d矩阵)和下面的构造函数/析构函数(还有其他方法,但我不认为它在这里是相关的):< / p>
class graph{
private:
bool** edges;
int size;
public:
graph(int size = 0):size(size){
edges = new bool*[size];
for (int i = 0; i < size; i++){
edges[i] = new bool[size];
}
}
~graph(){
for(int i = 0; i < size; ++i) {
delete [] edges[i];
}
delete [] edges;
}
//others methods
};
在我的主要内容中,我想使用动态分配:
int main()
{
int size;
cout << "Enter graph size :" << endl;
cin >> size;
graph g1 = new graph(size);
//some processing code
return 0;
}
然而,我在实例化时遇到错误(即新图(大小)):
从'graph *'无效转换为'int'[-fpermissive]
我真的不知道出了什么问题,而且我很确定这是我在其他地方已经看到的语法。
实际上,我并没有真正了解内存分配如何与对象的创建一起工作。
在这里,我在构造函数中使用 new 来创建bool 2d-matrix,所以它会进入堆,不是吗? 但是如果我使用以下静态指令实例化对象: 图g1(const_size);
然后它不打算去堆栈?
提前感谢您的回答。
修改
最后一个问题:
graph * g1 =新图表(大小);
将g1(指针)存储在堆栈上,但是在堆上创建了对象。
图g1(大小);
正在堆栈上创建对象,g1是对它的引用。
但无论如何,矩阵边缘会在堆上?或者在第二种情况下,它会以某种方式在堆栈上结束?
答案 0 :(得分:3)
错误在于:
graph g1 = new graph(size);
这应该是:
graph *g1 = new graph(size);
原因如下:
new graph(size)
正在创建新的graph
对象,它正在返回指向它的指针(使用graph*
类型),并且:
graph g1 = ...
正在尝试将其转换为对象int
(以便调用graph(int)
构造函数) - 因此错误为invalid conversion from 'graph*' to 'int'
。
现在,我认为这是一种练习,因为在这个例子中你不应该在堆上使用分配。但是如果你还是使用它,不要忘记:
delete g1;
实际上,我并没有真正了解内存分配如何与对象的创建一起工作。
graph *g1 = new graph(size);
在堆栈上存储g1
(指针),但是在堆上创建了对象。
graph g1(size);
正在堆栈上创建对象,g1
是对它的引用。
P.S。避免这样:
graph g1 = graph(const_size);
这将首先创建语句的右侧,它将是临时graph
对象,它将使用copy-constructor初始化g1
。
但是,例如,如果我想要一个可以处理各种图形大小的程序,而不是每次我想要使用不同的大小时重新编译它,我会需要类似的东西,不是吗?
不,你可以使用堆栈分配(我刚刚注意到在你的例子中,你使用const_size - 参数在堆栈上分配的对象的构造函数不需要是常量):
int size;
std::cout << "Enter size: ";
std::cin >> size;
graph g1(size);
是的,这里不需要动态分配,我只是做了那些代码来练习自己。但是如果我想在不重新编译的情况下使用各种大小的图形,那就没有必要吗?
不,请看上面的示例 - 堆栈分配的对象具有可变大小 - 无需重新编译。
我认为我们不应该自己调用析构函数,当我们超出范围时,它会被调用吗? (我甚至读到在某些情况下调用它实际上很糟糕,因为它可能是第二次调用它)
在堆栈分配的对象的情况下也是如此 - 析构函数将在作用域的末尾被调用。但是,如果在堆上分配对象,则在调用delete
之前不会调用析构函数。
但无论如何,矩阵边缘会在堆上吗?
edges = new bool*[size];
for (int i = 0; i < size; i++){
edges[i] = new bool[size];
}
是的,整个矩阵都在堆上分配。