G ++提供了神秘的错误消息,一些指针问题

时间:2013-04-23 05:40:03

标签: c++ arrays g++

我是C ++的新手,并努力尝试使多文件程序工作。我有一个用C语言运行的Graph库,我遇到了将它转换为C ++的麻烦。我最大的问题是g ++是这个错误信息,

error: no match for âoperator=â in â*(((Graph*)this)->Graph::adj +
((long unsigned int)(((long unsigned int)i) * 32ul))) = (operator
new(32u), (<statement>, ((List*)<anonymous>)))â

以下是我抱怨的Graph.cpp代码部分:

Graph::Graph(int n){
    order = n;
    size = 0;
    source = NIL;
    color = static_cast<char*>(calloc(n + 1, sizeof(char)));
    distance = static_cast<int*>(calloc(n + 1, sizeof(int)));
    parent = static_cast<int*>(calloc(n + 1, sizeof(int)));
    adj = static_cast<List*>(calloc(n + 1, sizeof(List*)));
    discover = static_cast<int*>(calloc(n + 1, sizeof(int)));
    finish = static_cast<int*>(calloc(n + 1, sizeof(int)));
    int i;
    for(i = 0; i <= n; i++){
        color[i] = 'w';
        distance[i] = INF;
        parent[i] = NIL;
        adj[i] = new List();
    }
}

正如您所看到的,我在C和C ++之间使用了一些混合,但纯C ++实现也不起作用。继续在我的文件中,我经常得到错误“错误:“的基本操作数“有非指针类型âListâ”,我认为这一切都来自于我如何声明。我在这里环顾四周,发现其他人抱怨这个错误,但我没有看到它有助于分配一个数组。帮助会很棒,因为除此之外我知道一切都有效。

3 个答案:

答案 0 :(得分:2)

您已将Graph::adj声明为List*类型(adj[i]与执行*(adj+i)相同),并取消引用指向T类型的指针产生类型T的值,即。 adj[i]的类型为List

如果你真的想要做你想做的事情,将Graph::adj声明为List**,那么它将指向一堆指向List的指针,而不是指针到了一堆List s。


我不明白,你想说什么?

您正尝试将List*(由new List返回)分配给List类型的变量。

struct List {
  // ... 
};

List ** adj = static_cast<List**> (
  std::calloc (10, sizeof (List*))
);

/* error

   List * adj = static_cast<List*> (
     std::calloc (10, sizeof (List*))
   );

*/

adj[0] = new List;

好的,我找到了你......但是必须有更好的方法来解决这个问题吗?

肯定的是,使用c ++为你提供的东西,抛弃旧的C习惯。

List * adj = new List [10]; // create an array of 10 List

adj[i].member_of_List ...;  // example

delete [] adj;              // free up allocated memory when you are done

答案 1 :(得分:1)

adj = static_cast<List*>(calloc(n + 1, sizeof(List*)));

建议 adj 列表对象的数组,而行

adj[i] = new List();

表明它是一个指针数组。您应该检查 adj 的定义。顺便说一下,错误是指后一行。

<强>类型

我将详细阐述问题的理论方面,围绕C ++类型系统。

在C ++中,每个表达式都有一个 type ,在编译时已知。 表单的任何表达式的类型

static_cast<List*>(...)

List *

也就是说,如果括号中的表达式的类型可以静态地转换为List *,则编译器不会抱怨并且表达式的最终类型将是List *。函数 calloc 返回void *,可以将其转换为任何其他指针;实际上,指针强制转换通常只是告诉编译器的一种方式是的,我知道我在做什么,闭嘴。在大多数平台上,所有指针类型都具有相同的位表示,尽管标准不强制要求这样做,因此原则上不需要生成机器代码来实现这样的转换。

表达式的类型,例如

new List()

new List[10]

List *

并且包含此类指令的指令为 List 对象或10个列表对象分配足够的空间,并返回指向此类空间的指针。

如果替换

,你可能会更好
adj = static_cast<List*>(calloc(n + 1, sizeof(List*)));

adj = new List[n + 1];

如果 adj 是指针类型,则表达式的类型如

adj[i]

*(adj + i)

甚至只是

*adj

是指针类型减去的一个星号;也就是说,如果 adj 的类型是

List *

adj [i] 的类型是

List

这就是为什么你在 adj [i] = new List()行获得错误的原因;分配

是没有意义的
List *

List

好消息是,如果您使用运算符分配 adj ,则可能不需要每次都使用 new 进行创建单一元素;当您使用 new 分配数组时,会创建其所有元素,并且编译器会自动调用它们的构造函数。

可能的解决方案

由于你的程序的其余部分非常正确,你可以简单地删除

adj[i] = new List()

一切都应该正常。然而,正如 john 所指出的那样,你的意图并不是很清楚;你真的需要告诉我们你是否希望 adj 成为一个对象数组

List *adj;

或指针数组

List **adj;

高级主题

使用C方式之间的实际区别

adj = static_cast<List*>(calloc(n + 1, sizeof(List*)));

或C ++方式

adj = new List[n + 1];

是否使用前一种方法调用每个已分配的 List 对象的构造函数。有一些指针的应用程序你可能希望这样,但一般情况下你不应该混合使用C和C ++。

答案 2 :(得分:0)

C和C ++的混合组合实际上比纯C ++更难。

在这种情况下,问题似乎是你有

class Graph
{
    ...
    List* adj;
    ...
};

所以

adj[i] = new List();

是错误的,因为adj[i]的类型为Listnew List()的类型为List*

对此的修复是使用 placement new

#include <new>

new (adj + i) List();

这将构建List地址&adj[i],这是我想要实现的目标。

但这是高级C ++,只是因为你正在尝试编写C和C ++的混合体。我会尽快抛弃C部分。

修改

好的,因为refp指出(我错过了)你有

adj = static_cast<List*>(calloc(n + 1, sizeof(List*)));

我的答案是正确的,如果这是一个错误而你打算

adj = static_cast<List*>(calloc(n + 1, sizeof(List)));