实例化 2D 数组并在C++中使用它

Instantiating a 2d array and using it in C++

本文关键字:C++ 2D 数组 实例化      更新时间:2023-10-16

我很了解C(10年),但我是一个C++新手。我得到以下错误:

hw2.cpp: In function ‘int main()’:
hw2.cpp:337:7: error: no match for ‘operator=’ (operand types are     ‘Graph’ and ‘Graph*’)
grph = new Graph(size);
   ^
hw2.cpp:337:7: note: candidate is:
hw2.cpp:17:7: note: Graph& Graph::operator=(const Graph&)
class Graph {
   ^
hw2.cpp:17:7: note:   no known conversion for argument 1 from ‘Graph*’   to ‘const Graph&’

我的类和构造函数是:

class Graph {
//
//  Class Graph --  contains the graph x, y of size Size showing          connectivity
 //                 (whether node X is connected to node Y) and the cost of
 //                 the connection between X and Y.
//
private:
int nNodes;
vector<vector<int>> gph;
public:
//
//  Constructors
//
explicit Graph(int size=50):nNodes(size){
    gph = new int *[size];
    for (int i = 0; i < size;i++)
        gph[i] = new int[size];
}
//
//  Destructors
//
~Graph(void){
    retgph();
}
//
//  Methods
//
void retgph(){
 }
 int getLength(
    int x,      // Node x
    int y){     // Node y
    return (gph[x][y]);
}
void setGraph(
    int nodeX,  // Node X
    int nodeY,  // Node Y
    int value   // Value to set it to.
    ){
gph[nodeX][nodeY]=value;
gph[nodeY][nodeX]=value;
return;
}
};

我的主代码是:

int main(){
Graph abc;  // graph object.
Open  opn;  // open set object.
int final;  // final node which should be destination.
const int size = 10;
const int source=0; // source node.
const int dest=5;   // destination node.
abc = new Graph(size);
opn  = new Open(size);

请耐心等待,因为我不知道我在做什么。我认为 ABC =新图形(50)应该实例化一个对象 ABC,但该图是在构造函数 Graph(int= size) 中构建的,并且是 GPH。当我说ABC.setNodeValue(1,2,3)时,我访问的是什么图; ?类中的图形 GPH 或其他 ABC 实例化?如果是实例化的一个(ABC),为什么GPH会出现在类图中?我的想法是ABC是将被方法操纵的(ABC.getNodeValue(47);)。类中的 GPH 是否只是作为实例化过程的模型出现在那里?此外,GPH实际上是INT **GPH; 。您能给我的任何帮助将不胜感激。

当你最初说Graph abc;你在堆栈上构造一个Graph对象时(使用它的默认构造函数,在本例中是一个默认的转换构造函数,图形的大小为 50)。

然后,您尝试将类型为 Graph * 的内容分配给此变量,因为这是 new 返回的内容(指向堆上新构造对象的指针),它显然与变量的类型不同。这就是为什么编译器抱怨这些类型之间缺少operator=(赋值运算符)的原因,并建议您改用复制赋值运算符,因为它与您尝试执行的操作非常匹配,但仍然不正确。也许您正在尝试执行以下操作:

const int size = 10;
Graph abc(size);
Open  opn(size);

或者,如果您确实要求通过指针存储它们:

const int size = 10;
Graph *abc = new Graph(size);
Open  *opn = new Open(size);
// Do stuff...
delete opn;
delete abc;

Graph类中,gph成员是一个包含std::vector元素的std::vectorstd::vectornew[]delete[]的包装器,所以不需要直接使用它们来分配向量。 要在运行时更改std::vector的大小,可以使用其resize()方法,例如:

class Graph {
private:
    vector< vector<int> > gph;
public:
    explicit Graph(int size=50) {
        gph.resize(size);
        for (int i = 0; i < size; ++i)
            gph[i].resize(size);
    }
    /* You can even reduce the constructor even more,
    using the constructor initialization list, if you
    don't mind a little extra overhead temporarily...
    explicit Graph(int size=50)
        : gph(size, std::vector<int>(size) ) {
    }
    */
    /* not necessary to clear the vector during destruction,
    it is handled automatic by the vector's own destructor...
    ~Graph() {
        retgph();
    }
    */
    void retgph() {
        gph.clear();
    }
    int getLength(int x, int y) {
        return gph[x][y];
    }
    void setGraph(int x, int y, int value) {
        gph[x][y] = value;
    }
};

至于你的代码中的其余部分...

new运算符返回指向在堆上分配的新实例化对象的指针。 因此,new Graph分配一个Graph对象,在其上调用Graph()构造函数,并返回指向该对象的Graph*指针。

编译器错误是因为abc变量在堆栈上声明为Graph实例化对象,而不是Graph*指针。 因此,当您调用 abc = ... 时,您实际上是在调用 Graph::operator=() 复制赋值运算符(在本例中由编译器为您自动生成)。 该运算符期望const Graph&(对常量Graph对象的引用)作为输入,而不是Graph*(指向Graph对象的指针),因此"没有已知的从Graph*const Graph&的转换"编译器错误。

对于使用 Open 类的 opn 变量也是如此。

abcopn变量更改为指针,并在访问这些对象的方法时将任何.更改为->。 并且不要忘记在使用完对象后delete它们:

int main() {
    const int size = 10;
    Graph *abc;  // pointer to graph object.
    Open  *opn;  // pointer to open set object.
    abc = new Graph(size);
    opn  = new Open(size);
    //...
    abc->setGraph(x, y, value);
    opn->doSomething(parameters);
    //...
    delete opn;
    delete abc;
}

或者,使用std::auto_ptrstd::unique_ptr为您处理delete

#include <memory>
int main() {
    const int size = 10;
    std::uninque_ptr<Graph> abc( new Graph(size) );
    std::unique_ptr<Graph> opn( new Open(size) )
    //...
    abc->setGraph(x, y, value);
    opn->doSomething(parameters);
    //...
}

或者,只是继续在堆栈上实例化它们,但摆脱newdelete,并在退出时让它们在超出范围时main()自行销毁:

int main() {
    const int size = 10;
    Graph abc(size);
    Open opn(size);
    //...
    abc.setGraph(x, y, value);
    opn.doSomething(parameters);
    //...
}

现在,回答您的问题:

我认为 ABC =NEW GRAPH(50) 应该实例化一个对象 ABC,但该图是在构造函数 Graph(int= size) 中构建的,并且是 GPH。

abc = new Graph(50)实例化构造函数值为 50 的新Graph对象,然后将该对象指针分配给 abc 。 在内部,Graph构造函数使用指定的size实例化gph向量。

当我说ABC.setNodeValue(1,2,3)时,我访问的是什么图; ?类中的图形 GPH 或其他 ABC 实例化?

您正在访问 abc 对象,该对象在内部访问gph向量。

如果是实例化的一个(ABC),为什么GPH会出现在类图中?

它是位于abc对象内部的一段数据。 把Graph想象成一个信封,把gph想象成信封里的东西,abc想象成握着信封的手。 每次调用new Graph时,都会创建一个新信封,其中包含一个新gph

我的想法是ABC是将被方法(ABC.getNodeValue(47);)操纵的。

是的。

类中的 GPH 是否只是作为实例化过程的模型出现在那里?

不。 这是正在实例化的事情之一。

此外,GPH实际上是INT **GPH;

不在你显示的代码中。 但从逻辑上讲,这相当于二维std::vector在运行时的行为方式 - 指向动态数组(外部向量管理的内容)的指针(外部向量管理的内容)的指针(内部向量)到动态数组(内部向量管理的内容)整数(内部向量持有的内容)。

上述代码的 C 等效项如下所示:

struct Graph {
    int size;
    int **gph;
};
struct Open {
    //...
};
Graph* createGraph(int size=50) {
    Graph *g = (Graph*) malloc(sizeof(Graph));
    g->size = size;
    g->gph = (int**) malloc(sizeof(int**) * size);
    for (int i = 0; i < size; ++i)
        gph[i] = (int*) malloc(sizeof(int) * size);
    return g;
}
Open* createOpen(int size=50) {
    Open *o = (Open*) malloc(sizeof(Open));
    //...
    return o;
}
void retGraph(Graph *g) {
    for (int i = 0; i < g->size; ++i)
        free(gph[i]);
    free(g->gph);
    g->gph = NULL;
    g->size = 0;
}
void freeGraph(Graph* g) {
    retGraph(g);
    free(g);
}
void freeOpen(Open* o) {
    //...
    free(o);
}
int getLength(Graph *g, int x, int y) {
    return g->gph[x][y];
}
void setGraph(Graph *g, int x, int y, int value) {
    g->gph[x][y] = value;
}
void doSomething(Open *o, parameters) {
    //...
}
int main() {
    const int size = 10;
    Graph *abc = createGraph(size);
    Graph opn = createOpen(size)
    //...
    setGraph(abc, x, y, value);
    doSomething(opn, parameters);
    //...
    freeOpen(opn);
    freeGraph(abc);
}