理解“'const' 在顶层,这可能会降低代码的可读性而不会提高 const 的正确性”

Understanding "'const' at top level, which may reduce code readability without improving const correctness"

请考虑下面的代码,特别注意 get_length returns const size_t.

#include <stdio.h>

const size_t get_length(void)
{
    return 123;
}

void foo(void)
{
    size_t length = get_length();
    length++;
    
    printf("Length #1 is %zu\n", length);
}

void bar(void)
{
    // Still 123 because length was copied from get_length
    // (copy ellision notwithstanding, which is not the point here)
    size_t length = get_length();
    
    printf("Length #2 is %zu\n", length);
}

int main(void) {
    foo();
    bar();
}

输出:

Length #1 is 124
Length #2 is 123

我从 c​​lang-tidy 收到以下警告:

Clang-Tidy: Return type 'const size_t' (aka 'const unsigned long')
is 'const'-qualified at the top level,
which may reduce code readability without improving const correctness

此消息有两个关于 return 类型的部分:

我理解第一部分,就像在 foo 和 bar 中一样,因为调用者不需要将他们的局部变量指定为 const,最终 const 的正确性没有提高, 也就是说,没有什么可以阻止调用者忽略被调用者 return 是一个 const 对象的事实。

但我不确定“代码可读性降低”是什么意思 - 是否仅仅是因为它可能会给某些人错误的期望,即永远不会修改 return 类型?还是有其他东西只对更复杂的 return 类型才有意义?

我问是因为我不认为这里的可读性会降低,而且我只是不确定警告背后的意图是什么。谢谢。

1。 Const 正确性没有提高

返回值只能作为右值使用。无法更改右值,因此已经给出了 const 正确性。

2。代码可读性降低

你在引导 reader 误入歧途。

例子

/* the rest of your example... */

void baz(void)
{
    size_t length = get_length();
    length += 42;
    
    printf("Length #2 is %zu\n", length);
}

没有什么可以阻止length的改变。它由一个常量初始化,对,比如 size_t length = 123;

/* the rest of your example... */

void fu(void)
{
    const size_t length = get_length();
    length += 42; /* will give a compile-time error */
    
    printf("Length #2 is %zu\n", length);
}

您可以在那里使用 const,但 Clang-Tidy 将其标记为无效也是正确的。

Should useless type qualifiers on return types be used, for clarity?, Benefits of using “const” with scalar type? 下的相关问答涵盖了为什么 const 在这种情况下无效的部分。

关于为什么“代码可读性降低”的问题的另一部分,这是因为多余的 const 限定符可能会分散对 const' 的核心事实的注意力ness 不结转价值分配。例如,它可能会诱使客户端代码错误地认为 return 值 必须 也用于 const,例如const size_t val = get_length(); 这是不正确的,如发布的代码所示。

类似的警告也适用于争论。假设 const size_t get_length(); 的 return 值总是传递给另一个函数 baz(get_length());baz 的参数不需要(并且可以说不应该)声明为 const size_t 而只是简单的 size_tvoid baz(size_t);.