如果我的函数是const,那么参数也必须是const吗?

时间:2017-01-03 19:58:23

标签: c++ const

假设我有一个不应修改类中的参数或其他任何内容的函数,例如:

bool isPossible(int x1, int y1, int x2, int y2) const {
    return x1 < x2 && y1 < y2;
}

为了清楚起见,我应该将所有参数设置为const以及函数本身,还是只将函数设置为const(我现在的方式)就足够了?

那就是,它应该是这样吗?

bool AABB::isPossible(const int& x1, const int& y1, const int& x2, const int& y2) const {
    return *x1 < *x2 && *y1 < *y2;
}

7 个答案:

答案 0 :(得分:5)

函数是const和函数参数之间没有关系是概念上的。它们用于不同的目的:

  • Const函数表示该函数不应更改类成员
  • 参数为const函数,参数值不应在函数内改变

因此,如果你希望你的函数参数是const,你应该单独决定函数本身是const。

例如,在您的特定情况下,虽然您确实可以将函数参数声明为const,因为您没有在函数内部修改它们(尽管在这种特殊情况下可能不会增加太多)。

将参考参数设置为const更有意义(在需要时),如其他答案中所述。

答案 1 :(得分:2)

简答:不。

示例中的const表示

  some_object.isPossible(a,b,c,d);

some_object视为const,但与该函数对abcd的作用无关

如果参数是按值传递的(如示例中的x1等),则声明它们const是多余的和不必要的,因为在调用函数时,调用者提供的值会被复制 - 在函数中更改它们对调用者没有影响。

如果参数通过引用或指针传递,const很重要(其含义是传递的参数不会被函数逻辑更改)(如果存在)。这与函数本身的const无关。因此,参数可能是const或非const,而与函数本身无关。

没有错
  some_object.isPossible(a,b,c,d);

被允许更改ac(未指定const)但不允许更改bd(指定const }})。这些可以独立于some_object是否可以改变(即成员函数本身是const)来处理。

答案 2 :(得分:1)

函数上的const修饰符与其参数无关。它仅适用于属于classstruct的函数,在这种情况下,它通常被称为方法。 const方法只是意味着方法不会修改它所调用的类的实例,但不保证它的参数。

如果您想保证不修改参数,请将const添加到参数中。了解按值和参考传递参数之间的区别非常重要。在这种情况下,每个参数都是由值给出的,因此任何调用此函数的人都知道该函数不能修改赋予该函数的原始变量。使用const的唯一好处是您无法意外地分配参数。对于通过引用传递的参数,情况是不同的,如果要保证给函数的原始变量没有改变,则需要const的存在。

答案 3 :(得分:1)

如前所述,const成员函数和const函数参数是两个不同的概念。

以下代码说明了不同之处:

#include <iostream>

class MyClass
{
public:
    MyClass();
    void PrintState() const;
    void UpdateState(const int newA, const int newB);
private:
    int a;
    int b;
};

MyClass::MyClass()
    : a(10), b(20)
{}

void MyClass::PrintState() const
{
    /*
     * Note: the following is not possible due to the member function being const. 
     * a = 30;
     */
    std::cout << "A: " << a << ", B: " << b << std::endl;
}

void MyClass::UpdateState(const int newA, const int newB)
{
    /* 
     * Note: the following is not possible due to the parameters being const.
     * However, updating the data members is fine.
     * newA = 30;
     * newB = 40;
     */
    a = newA;
    b = newB;
}

答案 4 :(得分:1)

首先考虑到这两个声明声明了同一个函数

bool isPossible(int x1, int y1, int x2, int y2) const;
bool isPossible(const int x1, const int y1, const int x2, const int y2) const;

这两个函数不会更改传递给函数的原始参数。函数参数是它的局部变量。

因此,const限定符的使用仅影响函数体。

函数的相应第一个定义可以通过以下方式设想

bool isPossible(/* int x1, int y1, int x2, int y2 */ ) const
{
    int x1, int y1, int x2, int y2;
    //...
}

使用限定符时的第二个定义可以通过以下方式设想

bool isPossible(/*const int x1, const int y1, const int x2, const int y2*/) const
{
    const int x1, const int y1, const int x2, const int y2;
    //...
}

对于函数的调用者,如何在函数内声明局部变量是完全不重要的。如果函数通过引用接受相应的参数,那将是很重要的。但是对于上面的函数,参数由值传递,这些值是处理参数副本的函数。因此,是否使用限定词并不是很重要。它只对函数体实现有自我记录的意义。

让我们假设该函数调用其他函数并通过引用另一个函数传递第一个自己的参数。

bool isPossible(/*const int x1, const int y1, const int x2, const int y2*/) const
{
    const int x1, const int y1, const int x2, const int y2;
    //...
    call otherFunction( &x1 );
    //...
}

在这种情况下,如果您希望在所有函数执行期间x1的原始值相同,并且其他被调用函数不会错误地更改x1的值,则最好使用限定符const声明参数。

考虑以下示例

#include <iostream>

void g(int *x) { *x += 10; }
void g( const int *x ) { }

struct A
{
    void f(int x) const
    {
        int prev_x = x;

        g( &x );

        if (x != prev_x)
        {
        std::cout << "x = " << x << ". Oops, x was changed!" << std::endl;
        }
        else
        {
            std::cout << "x = " << x << ". x was not changed" << std::endl;
        }
    }
};

int main()
{
    A().f(10);
}

功能输出

x = 20. Oops, x was changed!

问题在于,程序员错误地将指针强制转换为像这样的

指针
g(const_cast<const int *>( &x ));

为了避免这样的错误,使用限定符const

声明参数是有意义的
void f( const int x) const
{
    //..

为呼叫选择正确的重载功能

g( &x );

答案 5 :(得分:0)

const函数你的意思是const这个指针,这意味着该成员函数不会改变或修改类成员而不是参数。

不应修改按值传入的参数,因此建议将它们用作const。这在函数体很大并且使用它们时非常有用,以避免意外修改它们作为常量传递它们。在你的情况下,只要没有大代码就可以将它们作为常量或可修改的方式传递。

答案 6 :(得分:0)

不,您也不需要将参数设为const。传递参数的方式是按值进行的,因此您的参数只是原始的副本。

const参数的好处来自于在C / C ++中通过引用传递指针或值。