C ++:operator new和default构造函数

时间:2014-01-04 11:09:30

标签: c++ constructor new-operator dynamic-allocation

我无法理解如何使用构造函数进行动态分配。

我在我的代码中使用了一个名为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是对它的引用。

但无论如何,矩阵边缘会在堆上?或者在第二种情况下,它会以某种方式在堆栈上结束?

1 个答案:

答案 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];
    }

是的,整个矩阵都在堆上分配。