本文介绍了声明会影响std名称空间吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#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;
}

我希望输出是-55,但是输出是-5-5.

I expected that the output will be -5and 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名称空间吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-27 19:29
查看更多