这可能会导致无限循环

Might this cause an infinite loop?

本文关键字:无限循环      更新时间:2023-10-16

对于定义函数的第二个const版本,这样做是否保证安全?看起来它会有无限递归,因为我想返回const但我想要调用的另一个函数是 non-const。

它适用于 g++,但我担心这是不安全的。

#include <iostream>
using namespace std;
class test {
public:
   int* doSomething(int a) {
      int* someInt = new int(a);
      return someInt;
   }
   const int* doSomething(int a) const {
      return doSomething(a);
   }
};
int main() {
   test a;
   cout << *a.doSomething(12345) << endl;
   return 1;
}

不完全是:正如@Pete Becker在评论中指出的那样,如果您调用了将递归的const版本:

class test {
public:
   int* doSomething(int a) {
      int* someInt = new int;
      *someInt = a;
      return someInt;
   }
   const int* doSomething(int a) const {
      return doSomething(a);
   }
};
int main() {
   const test a;
   // You're not in for a good time:
   a.doSomething(12345);
   return 1;
}

在提供需要重复代码的函数的const和非const版本时,最好实现const版本,然后让非const版本以特定方式调用它。

来自斯科特迈尔斯有效C++ - 第三版:

const和非const成员函数具有基本相同的实现时,可以通过让非const版本调用const版本来避免代码重复

斯科特·迈尔斯(Scott Myers)继续为此提供了一种安全的方法:

const int* doSomething(int a) const
{
   int* someInt = new int;
   *someInt = a;
   return someInt;
}
int* doSomething(int a)
{
   return const_cast<int*>(static_cast<const Test&>(*this).doSomething());
}

在非const版本中,有两种演员阵容:static_cast基本上将this变成const this,其中const_cast抛弃了回归的const性。这样做是安全的,因为要调用非const版本,您必须具有非const this

但是,如果您只是提供对成员的访问权限,则只需具有以下内容即可简单易读:

class TestAccess;
class Test
{
    TestAccess& t;
public:
    const TestAccess& getA() const { return t; }
    TestAcess& getA() { return t; }
};

在这种情况下,编译器总是会选择函数的非常量版本,甚至不会调用常量版本。否则编译器将无法编译,您正在制动 constenss。例如,我快速修改了代码:

#include <iostream>
using namespace std;
class test {
public:
    int* doSomething(int a) {
        int* someInt = new int;
        *someInt = a;
        return someInt;
    }
    int ax = 10;
    void somethingElse(int i)
    {
        ax = i;
    }
    const int* doSomething(int a) const {
        somethingElse(a);
        return 0;
    }
};
int main() {
    test a;
    cout << *a.doSomething(12345) << endl;
    return 1;
}

此示例无法编译,因为您正在 const 作用域内调用 const 函数。编译器不会让你这样做。

现在,我知道这是一个测试,但这样做你永远不会摆脱递归,它会永远循环,而且你在每次调用时都会通过分配堆来泄漏内存,这两件事一起会导致灾难。