Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 常量引用传递的类的引用成员行为的设计原因_C++_Reference_C++11 - Fatal编程技术网

C++ 常量引用传递的类的引用成员行为的设计原因

C++ 常量引用传递的类的引用成员行为的设计原因,c++,reference,c++11,C++,Reference,C++11,假设你有密码 #include <iostream> struct A{ int y; int& x; A():y(0),x(y){} }; void f(int& x){ x++; } void g(const A& a){ f(a.x); //f(a.y); } int main(){ A a; g(a); std::cout<<a.y<<std::endl; } 及 是允许的。

假设你有密码

#include <iostream>

struct A{
  int y;
  int& x;
  A():y(0),x(y){}
};



void f(int& x){
  x++;
}

void g(const A& a){
  f(a.x);
  //f(a.y);
}


int main(){
  A a;
  g(a);
  std::cout<<a.y<<std::endl;

}

是允许的。这非常清楚:我们有一个指向非常量int的常量指针。
但是在前面的引用示例中,如果引用是对象,为什么在这种情况下它们会作为指针?在这种行为下的设计策略是什么?在C++引用中,

通常是用指针来实现的。(我认为引用和指针的大小是相同的)

实际上,我通常认为引用是指针,但语法不同

如果引用是对象

不过,引用不是对象-它们是对对象的引用

你是对的,使引用本身保持常量并不是很有用:因为它们是不可重置的,所以在任何情况下都不能像指针一样进行变异

事实上,将引用视为具有特殊语法的常量指针(而不是指向常量的指针!)可能更有帮助

请注意,如果您想要一个间接指令,它将常量从裁判传递到引用对象(即,为了防止
f(a.x)
调用此处),您可以编写一个智能指针样式的东西来执行此操作


具体例子

struct A
{
    int x;
    int *p;
    int &r;

    A() : x(0), p(&x), r(x) {}
};
现在在
A
中:

  • a.x
    是一个可变整数
  • a.p
    是一个可变指针(因此我们可以重置它),指向一个可变int(我们可以更改它指向的整数的值)
  • a.r
    是对可变整数的引用
    • 请注意,由于我们无论如何都不能改变(重置)引用,因此引用本身不是常量,也不是可变的
。。。但是在
常数A b中

  • b.x
    是一个常量整数
  • b.p
    是指向可变int的常量指针(因此我们无法重置它)
  • b.r
    是对可变整数的引用
    • 注意constness是如何应用于A(指针或引用)的成员的,而不是传播到referent的

    • 标准中的实际语言为

      8.3.2参考文献[dcl.ref] 1-[…] [注:可将引用视为对象的名称。-结束注]

      因此,如果引用是对象的名称,而不是对象本身,那么使封闭结构为
      const
      会使名称
      const
      (这是毫无意义的,因为引用不能反弹),而不是对象本身是有意义的

      我们也看到

      6- 如果类型定义、类型模板参数或decltype规范表示类型TR 这是对类型T的引用,尝试创建类型“对cv TR的左值引用”将创建类型“对T的左值引用”[…]


      由于对cv对象的成员访问会创建cv左值,因此同样适用,并且cv限定将被取消。

      是相同的问题;不过,这可能还不够深入。@ecatmur:谢谢,这完全一样,我会把它链接起来,但是,正如你所说的,这个回答并没有比“因为它像指针一样”更进一步。引用不是对象,它们是对对象的引用。@ereOn我同意,但请参见@FabioDallaLibera:我读过它。请注意,已接受答案中的“是”被强调,表明在解释这句话时需要小心。在某些特定情况下,将引用视为对象有时是可以接受的,因为它简化了逻辑。然而,重要的是要记住,引用在大多数情况下仍然是一种不同的野兽。“我认为引用和指针的大小是相同的”不,我也这么认为,尽管许多人强烈反对它,例如@Cheerrandhth.-Alf你是说它们从来都不一样还是只是有时候?@quamrana
      sizeof(T&)
      sizeof(T)
      相同。它与指针的大小无关。用于引用的内存大小可以是0或与
      T*
      相同,或者由编译器自行决定,并且不能通过
      sizeof
      获得(要检查它,您可以将引用放在
      结构中)。谢谢。我认为@UffuseComment在这里增加了一件重要的事情:引用本身const不是很有用:因为它们是不可重置的,所以在任何情况下都不能像指针一样进行变异。谢谢!这里是第6点:typedef int&C;模板结构V{const X&X;V(X&px):X(px){};intmain(){intx;ccc(x);vv(C);V.x=3;}谢谢。我喜欢你的回答。现在是下一步。结构B{int*x;}现在,常数B与具有int*const的B相同;但是,对于结构C{int&x;},x不是常量int&。你怎么称呼它?不,a
      const B
      有一个const成员x,也就是说
      int*const B::x
      。该成员是一个指针,因此const成员是一个const指针,而不是指向const的指针。因此,您仍然可以修改
      x
      指向的任何内容,但您不能修改
      x
      (通过重新放置)。谢谢。我为报告标准的摘录标记了@ecatmur response,但我也可以将您的答案标记为已接受的答案。我要把分数加起来
      g(const B&){
         *x++;
      }
      
      struct A
      {
          int x;
          int *p;
          int &r;
      
          A() : x(0), p(&x), r(x) {}
      };