问题描述
#include <iostream>
#include <cmath>
/* Intentionally incorrect abs() which seems to override std::abs() */
int abs(int a) {
return a > 0? -a : a;
}
int main() {
int a = abs(-5);
int b = std::abs(-5);
std::cout<< a << std::endl << b << std::endl;
return 0;
}
我希望输出是-5
和5
,但是输出是-5
和-5
.
I expected that the output will be -5
and 5
, but the output is the -5
and -5
.
我不知道为什么会发生这种情况?
I wonder why this case will happen?
与std
的使用有什么关系吗?
Does it have anything to do with the use of std
or what?
推荐答案
语言规范允许实现,以通过声明(并定义) global 命名空间中的标准函数,然后通过using-declaration将它们引入命名空间std
中来实现<cmath>
.尚不确定是否使用这种方法
The language specification allows implementations to implement <cmath>
by declaring (and defining) the standard functions in global namespace and then bringing them into namespace std
by means of using-declarations. It is unspecified whether this approach is used
显然,您正在处理一种决定采用这种方法的实现方式(例如GCC). IE.您的实现提供了::abs
,而std::abs
只是引用"了::abs
.
Apparently, you are dealing with one of implementations that decided to follow this approach (e.g. GCC). I.e. your implementation provides ::abs
, while std::abs
simply "refers" to ::abs
.
在这种情况下仍然存在的一个问题是,为什么除了标准的::abs
之外,您还可以声明自己的::abs
,即为什么没有多重定义错误.这可能是由某些实现(例如GCC)提供的另一个功能引起的:它们将标准函数声明为所谓的弱符号,因此允许您用自己的定义替换"它们.
One question that remains in this case is why in addition to the standard ::abs
you were able to declare your own ::abs
, i.e. why there's no multiple definition error. This might be caused by another feature provided by some implementations (e.g. GCC): they declare standard functions as so called weak symbols, thus allowing you to "replace" them with your own definitions.
这两个因素共同产生了您观察到的效果:::abs
的弱符号替换也导致了std::abs
的替换.这与语言标准的吻合程度是个不同的故事……无论如何,请不要依赖这种行为-语言无法保证.
These two factors together create the effect you observe: weak-symbol replacement of ::abs
also results in replacement of std::abs
. How well this agrees with the language standard is a different story... In any case, don't rely on this behavior - it is not guaranteed by the language.
在GCC中,此行为可以通过以下简约示例来重现.一个源文件
In GCC this behavior can be reproduced by the following minimalistic example. One source file
#include <iostream>
void foo() __attribute__((weak));
void foo() { std::cout << "Hello!" << std::endl; }
另一个源文件
#include <iostream>
void foo();
namespace N { using ::foo; }
void foo() { std::cout << "Goodbye!" << std::endl; }
int main()
{
foo();
N::foo();
}
在这种情况下,您还将观察到第二个源文件中::foo
("Goodbye!"
)的新定义也会影响N::foo
的行为.这两个调用都将输出"Goodbye!"
.并且,如果您从第二个源文件中删除::foo
的定义,则这两个调用将分派到::foo
的原始"定义并输出"Hello!"
.
In this case you will also observe that the new definition of ::foo
("Goodbye!"
) in the second source file also affects the behavior of N::foo
. Both calls will output "Goodbye!"
. And if you remove the definition of ::foo
from the second source file, both calls will dispatch to the "original" definition of ::foo
and output "Hello!"
.
上面20.5.1.2/4给出的许可可以简化<cmath>
的实现.允许实现仅包含C样式的<math.h>
,然后在std
中重新声明功能,并添加一些特定于C ++的添加和调整.如果上面的解释正确地描述了问题的内部机制,那么它的主要部分取决于功能的 C样式版本的弱符号的可替换性.
The permission given by the above 20.5.1.2/4 is there to simplify implementation of <cmath>
. Implementations are allowed to simply include C-style <math.h>
, then redeclare the functions in std
and add some C++-specific additions and tweaks. If the above explanation properly describes the inner mechanics of the issue, then a major part of it depends on replaceability of weak symbols for C-style versions of the functions.
请注意,如果在上述程序中仅将int
全局替换为double
,则代码(在GCC下)将表现为预期"-将输出-5 5
.发生这种情况是因为C标准库没有abs(double)
函数.通过声明我们自己的abs(double)
,我们不会替换任何内容.
Note that if we simply globally replace int
with double
in the above program, the code (under GCC) will behave "as expected" - it will output -5 5
. This happens because C standard library does not have abs(double)
function. By declaring our own abs(double)
, we do not replace anything.
但是,如果从int
切换为double
之后,我们也从abs
切换到fabs
,原始的怪异行为将再次显示出来(输出-5 -5
).
But if after switching from int
with double
we also switch from abs
to fabs
, the original weird behavior will reappear in its full glory (output -5 -5
).
这与上面的解释一致.
这篇关于声明会影响std名称空间吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!