C++ C++;常数问题

C++ C++;常数问题,c++,constants,C++,Constants,我对是否使类成员保持不变存在问题。让我举个例子 #include <iostream> class ValueClass { int ival; public: void set(int i) {ival = i;} int get() {return ival;} }; class XXX; class ABC { ValueClass vc; public: int getval() const {return vc.get() ;

我对是否使类成员保持不变存在问题。让我举个例子

#include <iostream>
class ValueClass
{
    int ival;
public:
    void set(int i) {ival = i;}
    int get() {return ival;}
};

class XXX;

class ABC
{
    ValueClass vc;  
public:
    int getval() const {return vc.get() ;}  
friend class XXX;
};

class XXX
{
    std::vector<ABC> abclist;
    void Invalidate()
    {
    // Iterates through abclist and modifies ValueClass members.
    // e.g. abclist[i].vc.set(i);
    }
};

class QWE
{
    const ABC & abc; 
public:
    QWE(const ABC & abc_): abc(abc_) { }
    const ABC & getABC() { return abc; } 
};

int main()
{
    ABC abc;
    QWE qwe(abc);

    std::cout << qwe.getABC().getval()  << "\n"; // Compiler error
}
#包括
类值类
{
国际竞争力;
公众:
空集(inti){ival=i;}
int get(){return ival;}
};
XXX类;
ABC班
{
价值等级vc;
公众:
int getval()常量{return vc.get();}
朋友班XXX;
};
XXX类
{
std::向量abclist;
无效
{
//迭代abclist并修改ValueClass成员。
//例如:abclist[i].vc.set(i);
}
};
QWE类
{
康斯特ABC&ABC;
公众:
QWE(const ABC&ABC_u1;):ABC(ABC_1;{}
const ABC&getABC(){return ABC;}
};
int main()
{
ABC;
QWE QWE(abc);
std::cout在ValueClass中设置get()常量

  class ValueClass
  {
      int ival;
    public:
      void set(int i) {ival = i;}
      int get() const {return ival;} // make get const
  };
可能对getABC也应该这样做

  const ABC & getABC() const { return abc; } 
这意味着此方法不会更改调用它的对象。

在ValueClass中设置get()常量

  class ValueClass
  {
      int ival;
    public:
      void set(int i) {ival = i;}
      int get() const {return ival;} // make get const
  };
class ValueClass
{
    ...
    int get() const {return ival;}
};

class QWE
{
    ...
    const ABC & getABC() const { return abc; } 
};
可能对getABC也应该这样做

  const ABC & getABC() const { return abc; } 
这意味着此方法不会更改它所调用的对象

class ValueClass
{
    ...
    int get() const {return ival;}
};

class QWE
{
    ...
    const ABC & getABC() const { return abc; } 
};
您的代码必须始终保持正确,否则您将一直遇到此问题


您的代码必须始终是常量正确的,否则您将一直遇到此问题。

正如其他人所指出的,访问器应该是常量合格的。一般来说,如果某些内容可以是常量合格的,那么它应该是常量合格的(当然,也有一些例外,例如,按值返回的函数的返回类型不应该是const限定的,尽管这通常并不重要)

<>但是,代码的另一个问题是:很容易使用错误和意外地丢失您的对象生命周期。如果您在代码< >()< /代码>中声明“<代码> QWE <代码> >为:

QWE qwe(ABC());
ABC()
构造一个临时的
ABC
对象并将其传递给
QWE
构造函数。由于构造函数参数
ABC
是一个
const ABC&
,它将绑定到该临时对象。然后通过初始值设定项
ABC(ABC)将成员引用
ABC
绑定到临时对象
。然后构造函数返回

构造函数返回后,临时的
ABC
对象被销毁,并且
qwe.ABC
是一个悬空引用:它不再引用对象


如果一个类将挂起您传递给它的引用,您应该更喜欢使用参数类型的指针:这样,您就更清楚地必须关注潜在的生存期问题。此外,引用类型类成员通常比它们本身更混乱,因为它们使类不可赋值(因为引用本身是不可分配的)。

正如其他人所指出的,访问者应该是const限定的。一般来说,如果某个东西可以是const限定的,那么它应该是const限定的(当然,也有一些例外,例如,按值返回的函数的返回类型不应该是const限定的,尽管这通常并不重要)

<>但是,代码的另一个问题是:很容易使用错误和意外地丢失您的对象生命周期。如果您在代码< >()< /代码>中声明“<代码> QWE <代码> >为:

QWE qwe(ABC());
ABC()
构造一个临时的
ABC
对象并将其传递给
QWE
构造函数。由于构造函数参数
ABC
是一个
const ABC&
,它将绑定到该临时对象。然后通过初始值设定项
ABC(ABC)将成员引用
ABC
绑定到临时对象
。然后构造函数返回

构造函数返回后,临时的
ABC
对象被销毁,并且
qwe.ABC
是一个悬空引用:它不再引用对象


如果一个类将挂起您传递给它的引用,您应该更喜欢使用参数类型的指针:这样,您就更清楚地必须关注潜在的生存期问题。此外,引用类型类成员通常比它们本身更混乱,因为它们使类不可赋值(因为引用本身是不可赋值的)。

实际上使(参见他的解决方案中的第4点)const在非内置类型上按值返回,尽管他承认这是有争议的。是的,我同意。使用指针要容易得多。但这里有一个想法“在现代C++中,指针只应用于编写库,而不是在实际应用程序代码中使用,因为引用会处理所有的事情,而且应该为此使用RAII。”我想也许我需要更多的参考文献。不要在应用程序代码中管理资源,而是在低级库代码中管理资源,然后在这些库设施上构建。”指针只是一种工具;它们对各种事情都非常有用。它们“不好”(需要引号)因为它们会使对象生命周期管理变得困难和复杂;然而,你在引用方面也有同样的生命周期管理问题。@Fred:是的;我读了那篇文章很多次,我几乎同意那里的所有内容。不过,我总是发现值返回类型的规则很奇怪和愚蠢:它没有任何意义,也没有任何意义const限定这样的返回类型并没有任何好处。此外,这是一个不能一致应用的规则,因为必须对基本类型进行特殊处理,这意味着在泛型代码中很难做“正确的事情”(特别是因为某些编译器,例如基于EDG的编译器,如果返回类型是基本类型,则当您对其进行const限定时,会向您发出警告)。实际上(参见他的解决方案中的第4点)在非内置类型上按值进行const返回,尽管他承认这是有争议的。是的,我同意。使用指针非常有用