C++ - const members/return const int&vs return int

Sim*_*ity 10 c++

这些C++行是什么意思?有没有其他方法来编写它们?

const int& a() const;
int getA() const;
Run Code Online (Sandbox Code Playgroud)

谢谢.

Dav*_*eas 10

这两个是类中成员函数的两个可能签名,它们承诺不更改对象本身.在第一种情况下,它将返回对整数(可能是成员属性)的常量引用,引用const意味着调用者将无法使用它来更改内部属性.第二种情况是它按值返回一个整数.

语义上有细微的差别,但在大多数情况下它们并不重要,将它们视为获取值的两个函数.对于会产生影响的情况,请看:

class test {
public:
   test() : m_value() {
      std::cout << &m_value << std::endl; // print where the attribute is
   }
   int const & getValue() const {
      return m_value;
   }
   int copyValue() const {
      return m_value;
   }
   void setValue( int value ) {
      m_value = value;
   }
private:
   int m_value;
};
int main() {
   test t;                      // will printout an address [1]
   int v1 = t.getValue();       // caller copies the value
   int v2 = t.copyValue();      // caller copies the value (itself a copy in hte calle)
   int const &r = t.getValue(); // reference to t.m_value
   int const &c = t.copyValue();// reference to *copy* [2]
   std::cout << v1 << v2 << r << c
      << std::cout;             // 0000
   std::cout << &v1 << &v2      // 4 pointers, the third is [1] a r *is* t.m_value
      << &r << &c << std::cout; //     the rest should be different
   t.setValue( 5 );
   std::cout << v1 << v2 << r   // 0050, v1 and v2 where copies, r *is* t.m_value
      << c << std::cout;
}
Run Code Online (Sandbox Code Playgroud)

标有[2]的行使用了该语言的一个奇怪特性,通过该特性,如果获得对r值(临时)的常量引用,编译器将临时绑定到引用并使其保持活动状态,直到引用超出范围(基本上它将r值暂时变为隐藏变量并将引用绑定到它).

我添加该行是明确的,因为行为的差异不是由于接收端main制作维护引用的副本,而是(准确地说)是访问者的签名.


Bal*_*arq 6

两者都是实现相同目标的等效方法:

const int& a() const;
int getA() const;
Run Code Online (Sandbox Code Playgroud)

你正在返回一个值.方法头右侧的const是一个注释函数getA()和一个()不会修改将执行它们的对象(隐藏的this参数).这在编译时很重要,因为这意味着在编译时会考虑额外的验证.在运行时,上面的函数和这些函数之间没有区别:

const int& a();
int getA();
Run Code Online (Sandbox Code Playgroud)

但是,扩展编译器的验证功能的巨大好处(当你不指望它发生时什么也没有改变)显然值得额外的 const.

需要担心的第二部分是两种函数的返回类型,它们代表了它们之间的主要区别,可能是问题的动机.让我们将主题更改为不同的功能:

std::string getName() const;
   { return name; }
Run Code Online (Sandbox Code Playgroud)

这里,返回值可能是类中的name属性.返回是通过值进行的,这意味着从此方法返回时将创建属性的副本.当字符串很大并且您在应用程序周围按值移动大量字符串时,这可能是一个问题.然后它恰好出现了返回引用机制,它承诺不复制:

std::string &getName() const
   { return name; }
Run Code Online (Sandbox Code Playgroud)

这实际上非常有趣:我们返回一个引用,而不是对象的副本.引用类似于指针,因此您只需复制指针(32位系统中的4个字节)而不是整个对象.这很有希望.但是,它甚至不会编译.编译将抱怨您在承诺方法为const时返回引用,因此,不会修改它将执行的对象.此代码将允许非法操作发生:

Person p( "Baltasar" );
p.getName() = "José";

cout << p.getName() << endl;
Run Code Online (Sandbox Code Playgroud)

这就是为什么返回类型的const看起来像一个新的有吸引力的选项,将解决问题.常量引用不允许修改它指向的对象,具有:

const std::string &getName() const
    { return name; }
Run Code Online (Sandbox Code Playgroud)

它现在将编译,而之前的恶意代码将不会.现在让我们回到我们的问题:

const int &getA() const;
int a() const;
Run Code Online (Sandbox Code Playgroud)

第二个是按值返回,这意味着int(4个字节)将在返回时被复制.第一个意味着将返回对int(4个字节)的常量引用.可以看出,在这种情况下,使用按引用返回而不是按值返回没有性能优势.

根据经验,通过const引用返回始终是安全的,它永远不会比按值返回更昂贵.