- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
在 C++ Primer 第五版中,它说:
int f(int){ /* can write to parameter */}
int f(const int){ /* cannot write to parameter */}
这两个函数无法区分。但是如您所知,这两个函数在更新参数的方式上确实存在差异。
谁能给我解释一下?
编辑
我想我没有很好地解释我的问题。我真正关心的是为什么 C++ 不允许这两个函数同时作为不同的函数,因为它们在“是否可以写入参数”方面确实不同。直觉上应该是!
编辑
按值传递的本质其实是通过将参数值复制到参数值来传递。即使对于引用 和指针,您复制的值是地址。从调用者的角度来看,无论是 const 还是 non-const 传递给函数都不会影响复制到参数的值(当然还有类型)。
top-level const 和low-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
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.
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/
我有一个用于重构练习的测试套件,我希望它与 Data.List 兼容。和 Data.List.NonEmpty .练习包含一个函数 foo :: [Foo] -> Foo并且测试套件有一些 data
我下载了 Android Studio 项目。项目根目录只有一个 build.gradle 具有下一个结构: apply plugin: 'com.android.library' android {
我似乎无法正确使用最接近的函数来删除删除按钮之外的 UL。 HTML X Data Jquery $('.remove').click(function(){
我需要一些帮助。顶级 Activity 必须位于自定义包之外吗?这样的话,MainActivity应该是在自定义包之外吧?Activity 是自定义包名称。
我正在尝试使用 AppCompat Drawer 和多个顶级 Activity (不是 fragment )创建一个基本应用程序 - 我不太清楚如何管理后台堆栈 - 我已经尝试了大约一百种不同的方法-
无法找到任何相关信息,我可以自己完成此操作,但我觉得将其保留在查询中可能是最好的选择(如果可能的话)。 基本上我想尝试添加查询的顶级“统计”部分。 所以当我得到结果时,我会看到这样的结果 num_ro
我在菜单中遇到 onmouseout/over delay 问题。我发现通过将 setTimeout 数字从 100 更改为 2000,它延迟了顶层菜单的隐藏而不是子级菜单,并且在新的 onmouse
是否有一个选项可以通过使用动画在运行时简单地 move Tkinter TopLevel() 窗口?我想到了由按钮触发的平滑 moveInAnimation。 这是一些代码片段: from Tkint
我从正在调用的 API 中获取了以下 JSON 文件: { "14500": [ { "5": { "versionName": "VersionOne",
在 C++ Primer 第五版中,它说: int f(int){ /* can write to parameter */} int f(const int){ /* cannot write to
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
我正在使用 Retrofit 进行一些 API 调用。对于特定端点,返回的 json 看起来有点像这样: 端点:api.example.com/1.0/userinfo?userid=7 返回的响应看
假设我有一个 Python 文件,我想在顶层运行它,但在它完成后,我想从它停止的地方继续。我希望能够使用它创建的对象等。 一个简单的例子,假设我有一个执行 i = 5 的 Python 脚本。当脚本结
我在 Xcode 中使用 Cmake 来生成一个 c++/c“项目”(my_project) 和一些 c++/c“目标”(一个是二进制文件,其余是库) 我的 CMakeLists.txt 看起来像这样
我正在尝试学习 redux,但遇到了错误。我只有两个文件,一个 index.html 文件和一个 main.js 文件,html 文件中有指向 jquery 和 redux cdns 的链接。我在 r
我有这个通用函数可以保存在 NSUserDefaults 中,通常可以正常工作,但现在我想保存一个 boolean 值,但出现错误。我找不到任何东西,我不明白为什么它不起作用。 extension U
我正在使用 Retrofit 进行 API 调用。顶级对象的命名取决于请求的查询参数。例如,这样的请求: api.somewebsite.com/1.0/mix_info?mix_id=69 返回这样
我做汤: from bs4 import BeautifulSoup soup = BeautifulSoup("My paragraph My link", "html.parser") 我想删除第
看完new egghead course由 Dan Abramov 撰写,我对提到的选择器有疑问。 选择器的目的是向组件隐藏状态树的详细信息,以便在树发生变化时便于以后管理代码。 如果我理解正确,那意
我是一名优秀的程序员,十分优秀!