C++ 为什么可以';t是一个“a”的指针;带有常量成员的结构”;键入指向“a”的点;具有非常量成员“的结构”;?

C++ 为什么可以';t是一个“a”的指针;带有常量成员的结构”;键入指向“a”的点;具有非常量成员“的结构”;?,c++,pointers,constants,const-pointer,C++,Pointers,Constants,Const Pointer,此代码不编译: struct s_t { int a; }; struct c_s_t { const int a; }; s_t s; c_s_t *c_s = &s; 然而,这一条汇编得非常完美: int a, *pa = &a, **ppa = &pa, ***pppa = &ppa; const int * const * const * const cpcpcpa = pppa; 我知道,在任何级别上更符合CV条件的指针都可以在任

此代码不编译:

struct s_t {
    int a;
};

struct c_s_t {
    const int a;
};

s_t s;
c_s_t *c_s = &s;
然而,这一条汇编得非常完美:

int a, *pa = &a, **ppa = &pa, ***pppa = &ppa;
const int * const * const * const cpcpcpa = pppa;
我知道,在任何级别上更符合CV条件的指针都可以在任何级别上指向不符合CV条件的对象,但为什么对结构不一样呢



上面的问题陈述是一个更复杂问题的MCVE,我的朋友试图在
t\u t
t\u t
之间转换指针,其中
t\u t
是一个带有一个模板参数
typename
的模板结构类型,
t
是一个任意类型。

这两个结构不同,而且它们是不能兑换的。他们拥有相同的成员这一事实是无关紧要的,即使您从
c\u s\t
中删除
const
,也不会改变任何事情

您的另一个示例之所以有效,是因为您将修改器应用于一种类型。例如,这是完全合法的:

struct s_t {
    int a;
};

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

这两个是不同的结构,它们不能转换。他们拥有相同的成员这一事实是无关紧要的,即使您从
c\u s\t
中删除
const
,也不会改变任何事情

您的另一个示例之所以有效,是因为您将修改器应用于一种类型。例如,这是完全合法的:

struct s_t {
    int a;
};

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

原因是
s_t
c_t
是不同的类型

即使您将
c\u s\t
定义为:

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

它仍然不起作用。

原因是
s_t
c_s_t
是不同的类型

即使您将
c\u s\t
定义为:

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

它仍然不起作用。

类型错误是您的问题您只是试图分配错误的类型

这将有助于:

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

类型错误是您的问题—您只是试图分配错误的类型

这将有助于:

s_t s;
s_t *c_s = &s; //types are matching
我知道,在任何级别上更符合CV条件的指针都可以指向任何级别上不符合CV条件的对象

这不是真的,至少不是你描述的那样。只有最上面的CV限定符可以任意添加(当然,指针本身上的CV限定符!),C和C++中都是这样的情况。 以下是“任何级别”概念的反例,直接取自当前标准草案中的
[conv.qual/3]

[ 注意:如果程序可以将
T**
类型的指针分配给
const T**
类型的指针(也就是说,如果允许下面的第1行),程序可能会无意中修改
const
对象(就像在第2行所做的那样)

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

不管怎样,你会问:

但是为什么结构不一样呢

当然,您可以将
常量T*
指向
T
,但这不是您要做的。此规则不会递归应用。类可以包含多个成员,因此您的方法通常不起作用(对于单成员类,不需要特殊规则)

在这种特殊情况下,这两个类是布局兼容的,因此我希望在大多数情况下,
reinterpret\u 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);
}
struct\t{
INTA;
};
结构c_s_t{
常数INTA;
};
int main()
{
s_t s;
c_s_t*c_s=重新解释铸件(&s);
}
() 然而,看来最终你最好重新思考一下你的设计

tl;dr:不同的类型是不同的类型。

我知道,在任何级别上更符合CV条件的指针都可以指向任何级别上不符合CV条件的对象

这不是真的,至少不是你所描述的。只有最上面的CV限定符可以任意添加(当然,指针本身上的CV限定符!),C和C++中都是这样的。

以下是“任何级别”概念的反例,直接取自当前标准草案中的
[conv.qual/3]

[ 注意:如果程序可以将
T**
类型的指针分配给
const T**
类型的指针(也就是说,如果允许下面的第1行),程序可能会无意中修改
const
对象(就像在第2行所做的那样)

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

不管怎样,你会问:

但是为什么结构不一样呢

当然,您可以将
常量T*
指向
T
,但这不是您要做的。此规则不会递归应用。类可以包含多个成员,因此您的方法通常不起作用(对于单成员类,不需要特殊规则)

在这种特殊情况下,这两个类是布局兼容的,因此我希望在大多数情况下,
reinterpret\u 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);
}
struct\t{
INTA;
};
结构c_s_t{
常数INTA;
};
int main()
{
s_t s;
c_s_t*c_s=重新解释铸件(&s);
}
() 然而,看来最终你最好重新思考一下你的设计


太长了,读不下去了。< P> <强> TL;DR:不同类型是不同的。< C++ > > > > > > > > > > > > > > > > > > > > > > > >我直接引用了标准来说明我在说什么。g
const
在顶级指针对象级别,而不是您所声称的“任何”级别!我知道为什么“不太合格”的指针不能指向“更合格”的对象,这不是我要问的。@iBug我认为您对C的看法也不正确:(虽然这可能是一个GCC错误或扩展-我没有仔细研究过标准):对于任何限定符q,指向非q限定类型的指针可转换为指向该类型的q限定版本的指针;原始指针和转换指针中存储的值应与