gpt4 book ai didi

c++ - 顶级 const 不影响函数签名

转载 作者:可可西里 更新时间:2023-11-01 16:28:44 28 4
gpt4 key购买 nike

在 C++ Primer 第五版中,它说:

int f(int){ /* can write to parameter */}
int f(const int){ /* cannot write to parameter */}

这两个函数无法区分。但是如您所知,这两个函数在更新参数的方式上确实存在差异。

谁能给我解释一下?


编辑
我想我没有很好地解释我的问题。我真正关心的是为什么 C++ 不允许这两个函数同时作为不同的函数,因为它们在“是否可以写入参数”方面确实不同。直觉上应该是!


编辑
按值传递的本质其实是通过将参数值复制到参数值来传递。即使对于引用指针,您复制的值是地址。从调用者的角度来看,无论是 const 还是 non-const 传递给函数都不会影响复制到参数的值(当然还有类型)。
top-level constlow-level const 之间的区别在复制对象时很重要。更具体地说,复制对象时忽略顶级常量(不是低级常量),因为复制不会影响复制的对象。复制到或复制自的对象是否为 const 并不重要。
所以对于调用者来说,区分它们是没有必要的。从函数的角度来看,顶级 const 参数可能不会影响函数的接口(interface)和/或功能。这两个函数实际上完成的是同一件事。为什么要费心实现两个拷贝?

最佳答案

allow these two functions simultaneously as different function since they are really different as to "whether parameter can be written or not". Intuitively, it should be!

函数的重载是基于调用者提供的参数。在这里,调用者确实可以提供 const 或非 const 值,但从逻辑上讲,它对被调用函数提供的功能应该没有影响。考虑:

f(3);
int x = 1 + 2;
f(x);

如果 f() 在每一种情况下做不同的事情,那将是非常困惑的!这段调用 f() 的代码的程序员可以对相同的行为有合理的期望,可以自由地添加或删除传递参数的变量,而不会使程序无效。这种安全、理智的行为是您想要证明异常(exception)的出发点,而且确实有一个 - 当函数重载时,行为可以改变 ala:

void f(const int&) { ... }
void f(int&) { ... }

所以,我猜这就是您发现的不直观之处:C++ 为非引用提供了比引用更多的“安全性”(通过仅支持单一实现来强制执行一致的行为)。。 p>

我能想到的原因是:

  • 因此,当程序员知道非const& 参数的生命周期更长时,他们可以选择最佳实现。例如,在下面的代码中,返回对 F 中的 T 成员的引用可能会更快,但是如果 F 是一个临时的 (如果编译器匹配 const F&) 则可能需要按值返回。这仍然非常危险,因为调用者必须知道返回的引用仅在参数存在时才有效。
    T f(const F&);    T& f(F&);    // return type could be by const& if more appropriate
  • propagation of qualifiers like const-ness through function calls as in:
    const T& f(const F&);    T& f(F&);

Here, some (presumably F member-) variable of type T is being exposed as const or non-const based on the const-ness of the parameter when f() is called. This type of interface might be chosen when wishing to extend a class with non-member functions (to keep the class minimalist, or when writing templates/algos usable on many classes), but the idea is similar to const member functions like vector::operator[](), where you want v[0] = 3 allowed on a non-const vector but not a const one.

When values are accepted by value they go out of scope as the function returns, so there's no valid scenario involving returning a reference to part of the parameter and wanting to propagate its qualifiers.

Hacking the behaviour you want

Given the rules for references, you can use them to get the kind of behaviour you want - you just need to be careful not to modify the by-non-const-reference parameter accidentally, so might want to adopt a practice like the following for the non-const parameters:

T f(F& x_ref)
{
F x = x_ref; // or const F is you won't modify it
...use x for safety...
}

重新编译影响

除了为什么语言禁止基于按值参数的 const 特性的重载之外,还有一个问题是为什么它不坚持 的一致性声明和定义中的 const-ness。

对于 f(const int)/f(int)... 如果您在头文件中声明一个函数,那么最好不要包含 const 限定符,即使稍后在实现文件中定义也会有它。这是因为在维护期间,程序员可能希望删除限定符......从 header 中删除它可能会触发客户端代码的无意义重新编译,因此最好不要坚持让它们保持同步 - 事实上这就是编译器不这样做的原因如果它们不同,则不会产生错误。如果您只是在函数定义中添加或删除 const,那么它接近代码读者在分析函数行为时可能关心常量的实现。如果您在头文件和实现文件中都包含 const,那么程序员希望将其设为非 const 并忘记或决定不更新头文件以避免客户端重新编译,那么它比其他方式更危险,因为程序员在尝试分析导致对函数行为的错误推理的当前实现代码时,可能会考虑 header 中的 const 版本。这都是一个非常微妙的维护问题 - 只与商业编程真正相关 - 但这是不在界面中使用 const 指南的基础。此外,从接口(interface)中省略它更简洁,这对于阅读您的 API 的客户端程序员来说更好。

关于c++ - 顶级 const 不影响函数签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17208570/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com