请考虑以下代码:
typedef struct Person* PersonRef;
struct Person {
int age;
};
const PersonRef person = NULL;
void changePerson(PersonRef newPerson) {
person = newPerson;
}
由于某种原因,编译器抱怨只读值不可分配。但是const
关键字不应该使指针成为常量。有什么想法吗?
答案 0 :(得分:41)
请注意
typedef int* intptr;
const intptr x;
与:
不同const int* x;
intptr
是指向int的指针。 const intptr
是指向int
的常量指针,而不是指向常量int
的指针。
所以,在一个typedef指针之后,我不能再使它成为内容的const?
有一些丑陋的方式,例如gcc的typeof macro:
typedef int* intptr;
intptr dummy;
const typeof(*dummy) *x;
但是,如你所知,如果你知道intptr
背后的类型,那就毫无意义。
答案 1 :(得分:7)
const PersonRef person = NULL;
是
struct Person*const person= NULL;
所以你正在构建指针而不是对象。
答案 2 :(得分:6)
虽然上面的答案已经解决了问题,但我确实错过了原因......
所以可能是一条经验法则:
const
始终引用它的前任令牌。这个规则可以真正帮助你声明一个指向const指针或同样整洁的东西的指针。
无论如何,考虑到这一点,它应该明白为什么
struct Person *const person = NULL;
向可变结构声明 const指针。
考虑一下,你的typedef “群组” struct Person
指针令牌*
。
所以,写作
const PersonRef person = NULL;
您的编译器会看到类似这样的内容(伪代码):
const [struct Person *]person = NULL;
由于const
的左边没有任何内容,它会将令牌改为右struct Person *
常量。
我认为,这就是为什么我不喜欢通过typedef隐藏指针的原因,而我确实喜欢这样的typedef。怎么样写
typedef struct Person { ... } Person;
const Person *person; /*< const person */
Person *const pointer; /*< const pointer to mutable person */
并且编制者和人类应该很清楚,你要做什么。
答案 3 :(得分:2)
永远不要隐藏typedef背后的指针,这真的是非常糟糕的做法,只会创建错误。
一个臭名昭着的臭虫是声明为const的typedef:ed指针类型将被视为“指向非常量数据的常量指针”,而不是“指向常量数据的非常量指针”这是什么一个人直观地期待。这就是你的程序中发生的事情。
解决方案:
typedef struct
{
int age;
} Person;
const Person* person = NULL; // non-constant pointer to constant Person
答案 4 :(得分:0)
你得到了错误
error: assignment of read-only variable ‘person’
声明
person = newPerson;
因为您已将person声明为const,因此其值仅为只读.... const值无法更改
如果你打算改变那个可变的那么你为什么要把它改为常量?
删除const关键字,您的代码将正常工作
答案 5 :(得分:0)
作为Piotr(已接受)答案的补充,可以避免GCC特定的typeof
:
static_assert(std::is_same<const int *, std::add_const_t<std::remove_pointer_t<intptr>> *>::value, "not same via type_traits");
static_assert(std::is_same<const int *, std::remove_reference_t<decltype(std::as_const(*intptr()))>*>::value, "not same via decltype");
通过将foo_t<T>
更改为foo<T>::type
和/或使用boost的版本,甚至可以在C ++ 98中执行此操作,尽管从C ++ 11开始它只是非常好。
或者,使用两个不同的typedef,它们也适用于除普通指针之外的其他情况。例如,考虑每个容器的iterator
和const_iterator
typedef。