简体   繁体   English

为什么“具有const成员的结构”类型的指针不能指向“具有非const成员的结构”?

[英]Why can't a pointer of a “struct with const member” type point to a “struct with non-const member”?

This code doesn't compile: 该代码无法编译:

struct s_t {
    int a;
};

struct c_s_t {
    const int a;
};

s_t s;
c_s_t *c_s = &s;
ibug@ubuntu:~ $ g++ -fsyntax-only t.cpp
t.cpp:10:15: error: cannot convert ‘s_t*’ to ‘c_s_t*’ in initialization
 c_s_t *c_s = &s;
               ^

However this one compiles perfectly: 但是,此代码可以完美地编译:

int a, *pa = &a, **ppa = &pa, ***pppa = &ppa;
const int * const * const * const cpcpcpa = pppa;

I understand that a pointer that is more CV-qualified at any level can point to a less CV-qualified object at any level, but why isn't it the same for structures? 我知道在任何级别上具有更高CV资格的指针都可以指向在任何级别上具有更低CV资格的对象,但是为什么结构不一样?


The above problem statement is a MCVE of a more complex problem, where my friend was trying to convert pointers between t_s_t<T> and t_s_t<const T> , where t_s_t is a template struct type with one template parameter typename , and T is an arbitrary type. 上面的问题陈述是一个更复杂问题的MCVE,其中我的朋友正在尝试在t_s_t<T>t_s_t<const T>之间转换指针,其中t_s_t是具有一个模板参数typename的模板结构类型,而T是一个任意类型。

The reason is that s_t and c_s_t are different types. 原因是s_tc_s_t是不同的类型。

Even if you define c_s_t as: 即使将c_s_t定义为:

struct c_s_t {
    int a; // <-- non-const!
};

Then: 然后:

s_t s;
c_s_t *c_s = &s;

It is still not going to work. 它仍然无法正常工作。

Type error is your problem you are simply trying to assign the wrong types. 类型错误是您的问题,您只是在尝试分配错误的类型。

This would work: 这将工作:

s_t s;
s_t *c_s = &s; //types are matching

Those two are different structs, and they're not convertible. 这两个是不同的结构,它们是不可转换的。 The fact that they have the same members is irrelevant, and even if you removed const from c_s_t , it wouldn't change anything. 它们具有相同的成员这一事实无关紧要,即使您从c_s_t删除了const ,它也不会改变任何东西。

Your other example works because you're applying modifiers to one type. 您的其他示例之所以有效,是因为您将修饰符应用于一种类型。 For example, this is perfectly legal: 例如,这是完全合法的:

struct s_t {
    int a;
};

s_t s;
const s_t const* cs = &s;

I understand that a pointer that is more CV-qualified at any level can point to a less CV-qualified object at any level 我了解在任何级别上具有更高CV资格的指针都可以指向在任何级别上具有较低CV资格的对象

This isn't actually true, at least not in the way you've described. 这实际上是不对的,至少不是您所描述的那样。 Only the topmost CV-qualifier can be added arbitrarily (and, of course, a CV-qualifier on the pointer itself!), which is the case in both C and C++. 只能任意添加最高的CV限定词(当然,指针本身也可以添加CV限定词!),在C和C ++中都是这种情况。

Here's a counter-example for the "any level" notion, taken straight from [conv.qual/3] in the current draft standard: 这是“任何级别”概念的反例,直接取自当前标准草案的[conv.qual/3]

[ Note: If a program could assign a pointer of type T** to a pointer of type const T** (that is, if line #1 below were allowed), a program could inadvertently modify a const object (as it is done on line #2). [注意:如果程序可以将类型T**的指针分配给类型const T**的指针(也就是说,如果允许下面的第1行),则程序可能会无意中修改const对象(这样做就可以了)在第2行)。 For example, 例如,

 int main() { const char c = 'c'; char* pc; const char** pcc = &pc; // #1: not allowed *pcc = &c; *pc = 'C'; // #2: modifies a const object } 

— end note ] —尾注]

Anyway, then you ask: 无论如何,然后您会问:

but why isn't it the same for structures? 但是为什么结构不一样呢?

Sure, you can point a const T* to a T , but that's not what you're doing. 当然,您可以将const T*指向T ,但这不是您要做的。 This rule doesn't apply recursively. 此规则不适用于递归。 Classes can hold more than one member so your approach just doesn't work in general (and there's no need for a special rule for single-member classes). 类可以容纳一个以上的成员,因此您的方法通常无法正常使用(单成员类不需要特殊的规则)。

In this particular case, the two classes are layout-compatible, so I'd expect a reinterpret_cast to appear to work most of the time: 在这种情况下,这两个类在布局上是兼容的,因此我希望reinterpret_cast在大多数情况下都起作用:

struct s_t {
    int a;
};

struct c_s_t {
    const int a;
};

int main()
{
   s_t s;
   c_s_t *c_s = reinterpret_cast<c_s_t*>(&s);
}

( live demo ) 现场演示

However, it appears that aliasing on the merits of layout-compatibility is not actually well-defined so ultimately you're better off rethinking your design. 但是,似乎在布局兼容性优点上的别名实际上定义不明确,因此最终最好还是重新考虑设计。

tl;dr: Different types are different types. tl; dr:不同的类型是不同的类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么指向非const成员函数的指针不能指向const成员函数而相反? - Why pointer to non-const member function can't point const member function and opposite? 在非const成员函数中,为什么指向此非const,而decltype指针则为const? - In a non-const member function, why is point this non-const, while decltype pointer this is const? const成员函数中对此的非const指针 - Non-const pointer to this in const member function 为什么我可以从 const 方法调用非常量成员函数指针? - Why can I call a non-const member function pointer from a const method? const成员函数可以返回一个非const指针指向数据成员吗? - Can const member function return a non-const pointer to a data member? 将const结构引用转换为非const指针 - Converting const struct reference to non-const pointer 解析 const 和 non-const 成员 function 指针 - Resolve const and non-const member function pointer MSVC:使用 const 和非常量重载推断指向成员函数的指针 - MSVC: inference of pointer to member function with const and non-const overloads 在const成员函数中以此初始化非const指针 - Initialise non-const pointer with this in const member function 为什么可以在常量结构上调用非const成员函数? - Why can a non-const member function be invoked on a constant structure?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM