ODR的事情又来了 [英] The ODR thing again

查看:104
本文介绍了ODR的事情又来了的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我在带有标题的头文件中有非内联函数定义

这样的警卫:

#ifndef HEADER_GUARD_H

#定义HEADER_GUARD_H


int foo(){return 42; }

namespace {bar(){return 666; }

#endif


foo()的定义只会在任何给定的翻译中出现一次

单位,对吗? 翻译单元是文件范围的同义词,是不是?b $ b不是?我是否正确认为不需要实施来检测TU中的ODR

违规?因此,是否/可能/一致的

编译器可以编译代码,其中foo()在多个TU中定义?


我对标准的理解是未命名的命名空间中的名称

具有文件范围。这是否意味着我应该能够在

未命名的命名空间中定义bar()并且永远不会从具有

定义(在标题保护范围内)的文件中获得ODR违规#include在
内的多个TU中相同的程序?

-

NOUN:1。遗嘱遗留给他人的金钱或财产。 2.从祖先或前任或过去那里下来的东西:b
宗教自由的遗产。 ETYMOLOGY:MidE legacie,副手办公室,来自OF,来自ML legatia的
,来自L legare,以及deute,遗赠。 www.bartleby.com/61/

If I have a non-inline function definition in a header file with header
guards like this:
#ifndef HEADER_GUARD_H
#define HEADER_GUARD_H

int foo(){ return 42; }
namespace { bar() { return 666; }
#endif

that definition of foo() will only appear once in any given translation
unit, correct? "Translation unit" is a synonym for "file scope", is it
not? Am I correct that the implementation is not required to detect ODR
violations across TUs? Is it, therefore, /possible/ that a conforming
compiler could compile code where foo() is defined in multiple TUs?

My understanding of the Standard is that names within an unnamed namespace
have file scope. Does that mean I should be able to define bar() in an
unnamed namespace and never get an ODR violation from the file with the
definition (within header guards) being #included in in multiple TUs within
the same program?
--
NOUN:1. Money or property bequeathed to another by will. 2. Something handed
down from an ancestor or a predecessor or from the past: a legacy of
religious freedom. ETYMOLOGY: MidE legacie, office of a deputy, from OF,
from ML legatia, from L legare, to depute, bequeath. www.bartleby.com/61/

推荐答案

* Steven T. Hatton:
* Steven T. Hatton:

如果我在带头文件的头文件中有非内联函数定义

这样的守卫:

#ifndef HEADER_GUARD_H

#define HEADER_GUARD_H


int foo(){返回42; }

namespace {bar(){return 666; }

#endif


foo()的定义只会在任何给定的翻译中出现一次

单位,对吗?
If I have a non-inline function definition in a header file with header
guards like this:
#ifndef HEADER_GUARD_H
#define HEADER_GUARD_H

int foo(){ return 42; }
namespace { bar() { return 666; }
#endif

that definition of foo() will only appear once in any given translation
unit, correct?



如果头文件按预期使用。

If the header file is used as intended.


"翻译单元"是文件范围的同义词,不是吗?
"Translation unit" is a synonym for "file scope", is it not?



No.


实际上,翻译单元由程序文本组成

来自预处理一个C ++源文件。


文件范围是指任何类或函数之外的声明。

No.

In practical terms, a translation unit is comprised of the program text
that results from preprocessing of one C++ source file.

File scope refers to declarations outside any class or function.


我是否认为不需要实施来检测TU中的ODR

违规?
Am I correct that the implementation is not required to detect ODR
violations across TUs?



是的。

Yes.


因此,/可能/符合

编译器可以编译代码,其中foo()在多个TU中定义?
Is it, therefore, /possible/ that a conforming
compiler could compile code where foo() is defined in multiple TUs?



是(为了使代码正确,将函数声明为''inline'','

该关键字是什么for)

Yes (to make the code correct, declare the function as ''inline'', that''s
what that keyword is for).


我对标准的理解是未命名的命名空间中的名称

具有文件范围。
My understanding of the Standard is that names within an unnamed namespace
have file scope.



它们具有命名空间范围,这通常意味着文件范围。


" ;未命名"命名空间并不是真正未命名的,但是为该翻译单元生成了一个自动生成的唯一名称。


然后将该命名空间中定义的名称导入到全局

命名空间好像


namespace {void bar(){}}


被翻译为


命名空间veryUniqueName {void bar(){}}

使用命名空间veryUniqueName;


您可以从中识别对于

命名空间std(至少大多数学生都这样做)几乎一样。

They have namespace scope, which is what''s usually meant by "file scope".

The "unnamed" namespace is not really unnamed but has an automatically
generated unique name for that translation unit.

Names defined in that namespace are then imported to the global
namespace as if

namespace{ void bar(){} }

is translated to

namespace veryUniqueName{ void bar(){} }

using namespace veryUniqueName;

which you may recognize from having done just about the same for
namespace std (at least, most students do).


这是否意味着我应该能够在

未命名的命名空间中定义bar(),并且永远不会从文件中获得ODR违规,其中

定义(在标题保护中)是#included in in

内的多个TU是同一个程序吗?
Does that mean I should be able to define bar() in an
unnamed namespace and never get an ODR violation from the file with the
definition (within header guards) being #included in in multiple TUs within
the same program?



bar()不会违反ODR,而foo会这样。


-

答:因为它弄乱了人们通常阅读文字的顺序。

问:为什么这么糟糕?

A:热门发布。

问:usenet和电子邮件中最烦人的事情是什么?

bar() will not violate the ODR, while foo will.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?


Alf P. Steinbach写道:
Alf P. Steinbach wrote:

* Steven T. Hatton:
* Steven T. Hatton:


>
>

>"翻译单元"是文件范围的同义词,不是吗?
>"Translation unit" is a synonym for "file scope", is it not?



No.


实际上,翻译单元由程序文本组成

来自预处理一个C ++源文件。


No.

In practical terms, a translation unit is comprised of the program text
that results from preprocessing of one C++ source file.



因此,在编译C ++程序文件方面,表示源文件,

源文件中直接或间接的#included。这是

也称为翻译单元。

So, in terms of compiling a C++ program "file" means the source file, and
everything #included directly or indirectly in the source file. This is
also called a translation unit.


文件范围是指任何类或函数之外的声明。
File scope refers to declarations outside any class or function.



翻译单元是否有任何范围与文件

范围不一致?

Is there any scope in a translation unit which is not coincident with file
scope?


>因此,/可能/符合
编译器是否可以编译在多个TU中定义foo()的代码?
>Is it, therefore, /possible/ that a conforming
compiler could compile code where foo() is defined in multiple TUs?



是(为了使代码正确,将函数声明为''inline'',那个'

该关键字是什么对于)。


Yes (to make the code correct, declare the function as ''inline'', that''s
what that keyword is for).



为了迂腐,说文件范围内使用的存储类

说明符''static'是不正确的为此目的?我怀疑内联和静态在大多数情况下会产生相同的效果。

我发现使用一个未命名的命名空间有价值的地方不是

涉及函数,所以我可能应该避免使用
$中的函数b $ b是例子。我发现它有用的是定义const char []

变量作为模板参数传递。

To be pedantic, is it not more correct to say that the storage class
specifier ''static'' used at file scope is intended for that purpose? I
suspect both inline and static will have the same effect in most cases. The
one place in which I found the use of an unnamed namespace valuable was not
involving functions, so I probably should have avoided using a function in
the is example. Where I found it useful was in defining const char[]
variables to pass as template parameters.


>
>

>我对标准的理解是未命名的
命名空间中的名称具有文件范围。
>My understanding of the Standard is that names within an unnamed
namespace have file scope.



它们具有命名空间范围,这通常意味着文件范围。


" ;未命名"命名空间并不是真正未命名的,但是为该翻译单元生成了一个自动生成的唯一名称。


然后将该命名空间中定义的名称导入到全局

命名空间好像


namespace {void bar(){}}


被翻译为


命名空间veryUniqueName {void bar(){}}

使用命名空间veryUniqueName;


您可以从中识别对于

命名空间std(至少大多数学生都这样做)几乎完全相同。


They have namespace scope, which is what''s usually meant by "file scope".

The "unnamed" namespace is not really unnamed but has an automatically
generated unique name for that translation unit.

Names defined in that namespace are then imported to the global
namespace as if

namespace{ void bar(){} }

is translated to

namespace veryUniqueName{ void bar(){} }

using namespace veryUniqueName;

which you may recognize from having done just about the same for
namespace std (at least, most students do).



如果学生是指一个人读一本关于如何使用C ++编程的书,

和老师你的意思是这样的作者一本书,我会说使用

''使用命名空间''指令在由

教师编写的代码中比在任何时候更常见,或者曾经,在我的代码中。当我开始尝试

认真学习C ++时,我开始使用过时的文本,使用< iostream.h>

并将std :: cout放在全局命名空间中。当我编译代码时,我收到了

警告消息,告诉我我的代码使用了已弃用的功能。


这让我非常沮丧和愤怒。我向人们寻求帮助,他们告诉我如何用使用指令污染全局命名空间。

这个复杂的功能似乎毫无意义似乎

除了恐吓新手之外别无其他目的。因此,我b $ b调查了名称空间的正确含义和意图。

If by student you mean a person who reads a book on how to program in C++,
and teacher you mean an author of such a book, I will say that the use
of ''using namespace'' directives is far more common in code written by
teachers than it is, or ever has been, in my code. When I started trying
to learn C++ in earnest I began with outdated texts that used <iostream.h>
and put std::cout in the global namespace. When I compiled the code, I got
warning messages telling me my code was using deprecated functionality.

That made me very frustrated and angry. I asked people for help, and they
told me how to contaminate the global namespace with a `using'' directive.
It seemed rather pointless to have this convoluted feature which seemed to
serve no other purpose than to intimidate the novice. I therefore
investigated the proper meaning and intent of namespaces.


>
>

>这是否意味着我应该能够在
未命名的命名空间中定义bar(),并且永远不会从文件中获取ODR违规
定义(在标题保护中)在同一程序中的多个TU中包含#include?
>Does that mean I should be able to define bar() in an
unnamed namespace and never get an ODR violation from the file with the
definition (within header guards) being #included in in multiple TUs
within the same program?



bar()不会违反ODR,而foo会。


bar() will not violate the ODR, while foo will.



内联,静态和未命名命名空间的使用在

效果方面有何不同?也就是说,除了内联不适用于

变量这一事实。


Sutter和Alexandrescu建议反对所有这些。如果我正确理解

,这是因为它会导致目标代码的冗余实例

在运行时放在堆栈上。


然后有外部...

-

NOUN:1。遗嘱遗留给他人的金钱或财产。 2.从祖先或前任或过去那里下来的东西:b
宗教自由的遗产。 ETYMOLOGY:MidE legacie,副手办公室,来自OF,来自ML legatia的
,来自L legare,以及deute,遗赠。 www.bartleby.com/61/


* Steven T. Hatton:
* Steven T. Hatton:

* Alf P. Steinbach:
* Alf P. Steinbach:

>>
然后将[匿名命名空间]中定义的名称导入到全局
命名空间,就好像

namespace {void bar(){}}

被翻译为

命名空间veryUniqueName {void bar(){}}

使用命名空间veryUniqueName;

您可以从中识别对于
命名空间std(至少大多数学生都这样做)几乎一样。
>>
Names defined in [an anonymous namespace] are then imported to the global
namespace as if

namespace{ void bar(){} }

is translated to

namespace veryUniqueName{ void bar(){} }

using namespace veryUniqueName;

which you may recognize from having done just about the same for
namespace std (at least, most students do).



如果学生是指一个人读一本关于如何使用C ++编程的书,

和老师你指的是这样的作者一本书,我会说使用

''使用命名空间''指令在由

教师编写的代码中比在任何时候更常见,或者曾经,在我的代码中。


If by student you mean a person who reads a book on how to program in C++,
and teacher you mean an author of such a book, I will say that the use
of ''using namespace'' directives is far more common in code written by
teachers than it is, or ever has been, in my code.



对不起,我的意思是没有不尊重。

[snip]

Sorry, I meant no disrespect.
[snip]


如何使用内联,静态和未命名的命名空间的

效果有何不同?也就是说,除了内联不适用于

变量这一事实。


Sutter和Alexandrescu建议反对所有这些。如果我正确理解

,这是因为它会导致目标代码的冗余实例

在运行时放在堆栈上。


然后有外部...
How do the use of `inline'', `static'', and unnamed namespaces differ in their
effect? That is, other than the fact that `inline'' is not applicable to
variables.

Sutter and Alexandrescu advise against all of these. If I understand
correctly, this is because it leads to redundant instances of object code
being placed on the stack at runtime.

And then there''s extern...



这与链接和一个定义规则(ODR)有关。

链接:哪些名称与

翻译单位的声明匹配(绑定)。如果在运行时使用N,则必须将名称N的纯声明与N的定义匹配。一个例子,其中N只是在编译时使用的
因此不需要定义:sizeof(N)。


有外部链接,内部链接,没有联系。


当名称N具有外部链接时,N的纯粹声明可以与另一个翻译单元中的定义匹配。 ODR:除非N(/)
是(a)声明''内联''或(b)是模板专业化,否则必须

不超过一个定义。在特殊情况下(a)和(b),

这些情况确实相同,但没有一般的C ++解释性术语,如果有多个定义,则为
必须都是相同的(但违反要求没有

诊断),这意味着实际上

链接器可以选择它遇到的第一个定义并丢弃

休息,这就是在工具级案例(a)和(b)

的原因,多个定义被称为可废弃的记录。


当名称N具有内部链接时,N的纯声明只能与同一翻译单元中的定义匹配。这意味着

名称N可以在任意数量的

翻译单位中以不同或相同的方式使用。有两种方法可以获得内部联系:''静态''

和''const''; ''静态''用于此目的(它有太多

含义!)不推荐用于数据而不用于函数。


当一个名字N没有联系,纯粹的N声明与

任何定义都不匹配。这意味着如果在运行时使用N,则不能在其他地方声明和定义它,它必须在

声明中定义。本地类没有链接。


匿名命名空间的要点是保持外部链接(所以

,例如可以使用模板机制,因为实际的

模板参数必须具有外部链接)但是每个翻译单元名称提供唯一的

,以避免名称冲突

翻译单位。


我怀疑Herb和Andrei建议反对''inline'','static''和

匿名命名空间。

-

答:因为它弄乱了人们通常阅读文字的顺序。

问:为什么这么糟糕?

A:热门发布。

问:usenet和电子邮件中最烦人的是什么?

This has to do with linkage and the One Definition Rule (ODR).

Linkage: which names are matched (bound) to which declarations, across
translation units. A pure declaration of a name N must be matched to a
definition of N if N is used at run-time. An example where N is only
used at compile time and so needs no definition: sizeof(N).

There is external linkage, internal linkage and no linkage.

When a name N has external linkage a pure declaration of N can be
matched to a definition in another translation unit. The ODR: unless N
is (a) declared ''inline'' or (b) is a template specialization, there must
not be more than one definition. In the exceptional cases (a) and (b),
which are really the same case but has no general C++ desciptive term,
if there is more than one definition they must all be the same (but no
diagnostic required for violation), which means in practice that the
linker can just pick the first definition it encounters and discard the
rest, which is the reason that at the tool level cases (a) and (b)
multiple definitions are known as "discardable" records.

When a name N has internal linkage a pure declaration of N can only be
matched to a definition in the same translation unit. This means the
name N can be used, differently or in the same way, in any number of
translation units. There are two ways to get internal linkage: ''static''
and ''const''; ''static'' used for this purpose (it has far too many
meanings!) is deprecated for data but not for functions.

When a name N has no linkage a pure declaration of N isn''t matched to
any definition. That means that if N is used at run time it can''t be
just declared and defined elsewhere, it must be defined in the
declaration. A local class has no linkage.

The main point of an anonymous namespace is to keep external linkage (so
that e.g. the template mechanism can be employed, because actual
template parameters must have external linkage) but provide unique
per-translation unit names so as to avoid name conflicts across
translation units.

I doubt that Herb and Andrei advice against ''inline'', ''static'' and
anonymous namespaces in general.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?


这篇关于ODR的事情又来了的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆