質問

As I understand it (and I may be incorrect), when a program is compiled all of the source files are merged into one massive swath of code. At this stage can the entire program "see" the content of every other file's scope?

Here is a really simple example:

1.cpp

int X = 0;

2.cpp

string Y = "";

Is it safe to assume that 1.cpp will never see Y and 2.cpp will never see X? That is they can be anything and never conflict or cause issues?

役に立ちましたか?

解決

As I understand it (and I may be incorrect), when a program is compiled all of the source files are merged into one massive swath of code.

No. compilation takes place in translation units. A .cpp file will be compiled at a time. All of it's #included headers will be literally copied into the file, but the result will be compiled separately from other .cpps in your program. They are all then linked together at the end. This is when all the symbols and names are matched up.

If you declare your variables just like that, at "file scope", they will be visible to the rest of the program (although you need a declaration in the other file to actually use it. This is why the declaration would typically go in a header file). If you want translation unit scope, with no visibility outside and no risk of name clash, declare them inside an unnamed namespace:

// File 1
namespace {
    int X = 0;
}

and

// File 1
namespace {
    float X = 0.0; // No clash!
}

(Bear in mind that any actual implementation may do things it's own way with regard to compiling and linking, but I think I've described a reasonably typical model that you can pretend is true for thinking about most simple cases.)

他のヒント

I don't think it would cause any problems unless you have both these .cpp files precompiled. Only pre compiled headers are made global(unless you don't modify the make file).

In your example X and Y do not conflict with each other because they are different identifies. The both variables are defined in the global namespace and have external linkage. Of course 1.cpp will not see Y until Y will be declared in 1.cpp.

For example

1.cpp

extern string Y;

This is a declaration of the variable Y. It is not a definition. So the linker will consider this Y and Y in 2.cpp as the same one object.

However if you will define Y in 1.cpp for example as

1.cpp

int Y;

or even as

1.cpp

string Y;

then the linker will issue an error because it will find two definitions of objects with the same name with external linkage. And it will not know what definition to use.

At the same time you could define variable Y in 1.cpp as having internal linkage. For example

1.cpp

static string Y;

or

1.cpp

namespace
{
    string Y;
}

In both cases variable Y will have internal linkage. in thjis case this definition of Y will not conflict with the definition of Y in 2.cpp because variable Y in 1.cpp will not be seen outside 1.cpp. It will not be placed in the table of variables with external linkage and the linker will know nothing about it.

First, there is no such thing as file scope in C++. What you probably mean is global scope, which is just a special case of namespace scope.

And you have to distinguish between visibility and binding: the first determines what symbols you can access at a given place in the source code; the second determines what entity a symbol binds to. Within a given translation unit, you can never "see" a symbol which was not declared in that translation unit, in some way or another. In that sense, if you have int X; in one source file (1.cpp), and do not declare X in another source file (2.cpp), including in any headers included in the other source file, then X is not visible in the other source file. On the other hand, if you do accidentally try to define another entity named X in the second source file, the symbol will refer to the same entity as in the first source file; in the case where both declarations define a variable (as in your example), that is undefined behavior.

Because such undefined behavior can so easily occur unintentionally, you usually will not want to define variables (or other entities) in the global namespace unless you want them to be visible everywhere (in which case, you will put the appropriate declaration in a header). If you want the defined symbol to only be visible in a single translation unit, you will put it in unnamed namespace (which in fact has a magic name which is unique for each translation unit).

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top