2010-06-24 70 views
1

我有一个变量,这是一个链接列表头。我想使它成为const,因为它永远不会被改变,整个程序都会使用这个变量,所以我认为我应该让它成为一个全局常量。问题是我在声明它为const后无法初始化它。如何初始化一个全局的const指针?

我该如何解决这个问题?

typedef struct PT { 
int x; 
int y; 
struct PT *next; 
} POINT; 

//globals 
POINT * const mypoint_head; 

int main(int argc, char *argv[]) 
{ 
    int size = 100; 
    mypoint_head= InitPoint(size); // error C2166: l-value specifies const object 
    //rest of code 

} 


POINT* InitPoint(int size) 
{ 
    POINT *tmp; 
    POINT *orig; 
    int a = 10; 
    int b = 1000; 
    orig = (POINT*) malloc (sizeof(POINT) * size); 
    if(orig == NULL) 
     return NULL; 

    tmp = orig; 
    for (i = 0; i < size; i++) 
    { 
     tmp->x = a++; 
     tmp->y = b++; 
     if (i == size -1) { 
      tmp->next = NULL: 
     } 
     else { 
      tmp->next = tmp+1; 
     } 
     tmp++; 
    } 
    return orig; 
} 
+1

当你可以改变列表的其余部分时,const head ptr的优点是什么?这就像是给一间草屋加一个铁门。 – 2010-06-24 18:47:06

+0

@Amardeep:我认为这更像是用墨水写出某人的地址,而不是铅笔。不同的人可以进出,但房子总是在同一个地方(除非你住在肯塔基州)。 – 2010-06-24 19:46:46

+0

@Amardeep @Tim Schaeffer - 是的Tim,我的目的是为了防止改变我的“头部”指针,以后无法释放内存,泄漏它......有没有更好的方法来做到这一点?或者就像......这么简单,如果它是“头”,就不要改变它。我有一个不同的名字,并意外地改变了它的另一个功能,直到我意识到我不想这样做。 – emge 2010-06-24 20:14:44

回答

0

从全局声明中删除const限定符并将rest_of_code声明为一个函数,该函数采用const限定版本的指针。

//globals 
POINT * mypoint_head; 

void rest_of_code(POINT* const mypoint_head) 
{ 
    mypoint_head = NULL; // this errors out now 
} 
int main(int argc, char *argv[]) 
{ 
    int size = 100; 
    mypoint_head= InitPoint(size); // no longer errors out 
    //rest of code 
    rest_of_code(mypoint_head); 
} 

+0

为什么我想要使用全局参数的函数?是不是打败了全球化的目的? 另一方面,我可能不会让它成为一个全球性的,并使用您的策略... 什么是处理“头”链接列表,以便他们不被意外修改,并丢失内存的最佳方式是什么? – emge 2010-06-24 18:55:28

+1

错误,也许不是标记头为const,你应该提供列表操作的功能,并且只能通过这些功能访问列表。 – ninjalj 2010-06-24 18:59:45

+1

@ emge-如果您担心将头部丢到列表并泄漏内存,则静态声明头节点并动态声明列表的其余部分。这样,头节点就不会“丢失”。 – bta 2010-06-24 19:17:41

3

您不能 - 这就是const的全部要点。

0

你必须使用一个初始化的声明:

static POINT mypoint_data[100]; 
POINT * const mypoint_head = &mypoint_head; 

然后改变你的InitPoint功能采取的不是调用malloc的指针数据空间,并将它传递mypoint_data

您也可以坚持extern POINT * const mypoint_head;在头文件中,因此可以在其他编译单元中访问。

0

(假设c)中常量具有当它们被宣布为被初始化并且它们不能进行评估。也许你可以使用一个const指针,并使它指向你的头部并将其暴露给代码的其余部分。 如果我实现可能是我将用getListHead()函数暴露变量,并给它一些模糊的名字:)

奇迹的用例是什么,但。即使头指针改变,我也会让我的列表工作。 (如果我有一个const头,如果我必须删除头节点,我将不得不移动像在一个阵列中的元素)

1

你是正确的,因为变量声明const永远不能改变。不幸的是,您的mypoint_head= InitPoint(size);行会计入尝试更改变量。声明时,必须使用一个值初始化const变量。

尝试这样代替:

//globals 
static POINT head_of_list; 
POINT* const mypoint_head = &head_of_list; 

现在,您可以使用初始化列表:

mypoint_head->next= InitPoint(size-1); 

的头的列表对象被宣布为静态的,所以它总是存在的,你厄尔需要适当调整你的InitPoint参数。您也可以在另一个文件中使用对指针的引用,而不必让它指向的对象可以直接访问(对于它的价值)。

+0

谢谢bta ...我真的很喜欢你的解决方案,但我选择了另外一个实现,原因有两个: A)我不想混合静态和动态元素 B)我不想将参数更改为InitPoint – emge 2010-06-24 22:17:31

+0

“静态”部分纯粹是可选的;它会以任何方式工作。 – bta 2010-06-24 22:30:55

1

没人说得清这尚未:

int main(int argc, char *argv[]) 
{ 
    int size = 100; 

    // cast address of mypoint_head to a non-const pointer: 
    POINT ** nc_pmh = (POINT **)&mypoint_head; 
    // use the address to set mypoint_head: 
    (*nc_pmh) = InitPoint(size); 
    //rest of code 
} 

这可能不是在C++中,它可能不是真的const对象提供空间工作。

顺便说一句:这通常不是好的做法。然而,在这种情况下,它运作良好。

顺便说一句:你会想检查返回从InitPoint(),并采取相应的行动(可能调用exit())。

+0

谢谢Tim,我感谢你的聪明解决方案。 – emge 2010-06-24 22:22:27

1

没有一个全局常量指针作为您的其他接口。

使用功能: -

static POINT * mypoint_head; 

POINT* point_head() 
{ 
    return mypoint_head; 
} 
+0

...或者您可以接受宏:POINT * point_head_get(){return mypoint_head;}​​ #define point_head point_head_get() 这是如何在mingw中定义stdout的。 – user877329 2013-08-17 14:03:17

0

我不能相信,至今还没提出的const_cast ..它的工作原理只是为常数指针作为罚款。

const_cast<POINTER *>(mypoint_head) = InitPoint(size); 

很简单,没有额外的变量声明,没有。