值参数的Const正确性

时间:2009-11-12 17:42:02

标签: c++ pass-by-value const-correctness

我知道关于const正确性的问题很少,其中声明函数的声明及其定义不需要同意值参数。这是因为值参数的常量仅在函数内部很重要。这很好:

// header
int func(int i);

// cpp
int func(const int i) {
    return i;
}

这样做真的是最好的做法吗?因为我从未见过有人这样做过。我已经在其他地方看到过这个引用(不确定来源):

  

“实际上,对于编译器,无论是否在值参数前面包含此const,函数签名都是相同的。”

     

“避免在函数声明中使用const pass-by-value参数。如果不修改参数const仍然在同一函数的定义中。”

第二段说不要将const放在声明中。我假设这是因为值参数的常量作为接口定义的一部分是没有意义的。这是一个实现细节。

根据这个建议,是否也建议指针参数的指针值? (它对参考参数没有意义,因为您无法重新分配参考。)

// header
int func1(int* i);
int func2(int* i);

// cpp
int func1(int* i) {
    int x = 0;

    *i = 3; // compiles without error
    i = &x; // compiles without error

    return *i;
}
int func2(int* const i) {
    int x = 0;

    *i = 3; // compiles without error
    i = &x; // compile error

    return *i;
}

摘要:制作值参数有助于捕获一些逻辑错误。这是最佳做法吗?你是否将const留在头文件中?它对const指针值有用吗?为什么或为什么不呢?

一些参考文献:

C++ const keyword - use liberally? Use of 'const' for function parameters

const值参数何时有用的示例:

bool are_ints_equal(const int i, const int j) {
    if (i = j) { // without the consts this would compile without error
        return true;
    } else {
        return false;
    }
    // return i = j; // I know it can be shortened
}

7 个答案:

答案 0 :(得分:10)

我多次读过在函数const中创建值参数是一件坏事,因为它是不必要的。

但是,我觉得它有时对我有帮助,因为检查我的实现没有做我不想做的事情(如问题末尾的例子)。

因此,虽然它可能不会给调用者增加价值,但它有时会为我作为一个实现者添加一点点价值,并且它不会从调用者那里带走任何东西。所以我觉得使用它没什么坏处。

例如,我可能正在实现一个C函数,它接受一个指向缓冲区的指针 - 指向开始的指针和指向结尾的指针。我要将数据放入缓冲区,但是要确保我不会超出结束范围。因此,在函数内部有代码,当我向其添加数据时,它会递增指针。将指针指向缓冲区末尾的const参数将确保我不会编码一个错误地将结束边界指针递增而不是指针实际应该递增的错误。

所以fillArray函数的签名如下:

size_t fillArray( data_t* pStart, data_t* const pEnd);
当我真的想要增加pEnd时,

会阻止我意外地增加pStart。这不是一件大事,但我很确定在C中任何时间编程的每个人都遇到过这样的错误。

答案 1 :(得分:8)

我接受它:

这不是一个坏主意,但问题很小,你的精力可能会更好地花在其他事情上。

在你的问题中,你提供了一个很好的例子,说明何时可能发现错误,但偶尔你也会这样做:

void foo(const int count ...)
{
   int temp = count;  // can't modify count, so we need a copy of it
   ++temp;

   /* ... */
}

无论哪种方式,优点和缺点都很小。

答案 2 :(得分:1)

不幸的是,有些编译器(我正在看你,Sun CC!)错误地区分了声明为const的参数和未声明的参数,并且你可能会得到有关未定义函数的错误。

答案 3 :(得分:0)

我认为这取决于你的个人风格。

它不会添加或减去客户端可以传递给您的函数的内容。从本质上讲,它就像一个编译时断言。如果它可以帮助你知道价值不会改变,那就去做吧,但我没有看到其他人做这件事的重要原因。

我可能不会这样做的一个原因是值参数的常量是客户不需要了解的实现细节。如果您稍后(故意)更改您的函数以便实际更改该值,则需要更改函数的签名,这将迫使客户重新编译。

这类似于为什么有些人建议不使用公共虚拟方法(函数virtual-ness是一个应该从客户端隐藏的实现细节),但我不在那个特定的阵营中。

答案 4 :(得分:0)

如果存在const关键字;它意味着' i' (这是const类型)无法修改。 如果' i'的价值在foo函数内部更改编译器会抛出错误:"

  

无法修改const对象

但改变' *我' (即* i = 3;)意味着你没有改变' i'但是' i'指出的地址的价值。

实际上,const函数适用于不应被函数更改的大对象。

答案 5 :(得分:0)

我们都必须不时地解开其他人的C ++代码。根据定义,其他人的C ++代码完全混乱:D。

因此,在编译器抱怨之前,我总是将解密它(本地和全局数据流)的第一件事放在每个变量定义中const。这也意味着const限定值参数,它确实有助于避免在函数中间修改过的变量,而我却没有注意到它......

所以我非常感谢其他人在任何地方都有const(包括值参数):D

答案 6 :(得分:-2)

我喜欢这种情况的常态正确性:
void foo(const Bar &b) //I know b cannot be changed
{
//do something with b
}

这让我可以使用b而不用担心修改它,但我不需要支付复制构造函数的费用。

相关问题