简体   繁体   中英

Why is multiple definition of a const global variable allowed in C++ and not in C?

Multiple definition of a global variable is not allowed in C or C++ due to the One Definition Rule. However, in C++ a const global variable can be defined in multiple compilation units with no error. This is not the same as in C.

Why does C++ allow this while C does not? Why does the usage and behaviour of a const global differ from a non-const global in this way in C++ compared to C? What is happening under the covers with C++ and C with respect to const?

For example this is allowed in C++, but wrong in C:

// Foo.cpp
const int Foo = 99;

// Main.cpp
const int Foo = 99;
int main()
{
    cout << Foo << endl;
    return 0;
}

And this is fine with C, but wrong with C++:

// Foo.cpp
const int Foo = 99;

// Main.cpp
extern const int Foo;
int main()
{
    cout << Foo << endl;
    return 0;
}
// Foo.cpp
const int Foo = 99;

// Main.cpp
const int Foo = 99;

const variable at namespace scope has internal linkage. So they're basically two different variables. There is no redefinition.

From @David's comment, 3.5/3 [basic.link]:

A name having namespace scope (3.3.5) has internal linkage if it is the name of
— an object, reference, function or function template that is explicitly declared static or,
— an object or reference that is explicitly declared const and neither explicitly declared extern nor previously declared to have external linkage ; or
— a data member of an anonymous union.


In the second case, you should be doing this (correct way):

//Foo.h
extern const int Foo; //use extern here to make it have external linkage!

// Foo.cpp
#include "Foo.h"
const int Foo = 99; //actual definition goes here

// Main.cpp
#include "Foo.h"
int main()
{
   cout << Foo << endl;
}

I think you are asking for the rationale and not the specific language rule that allows this.

The rationale for this is that it makes const variables much easier to use. It gives a typed replacement for one common use of #define .

Instead of #define MAX_COUNT 211 you can use const int max_count = 211; in exactly the same way, eg a shared header file, without having to worry about where to put the one definition.

You can't legally change the value of a const object so there's no visible difference between having one object and multiple objects with the same value.

As you can put a definition of a const object in a header file it makes trivial for the compiler to use the value directly at the compilation stage without such optimizations having to be delayed to a link-time fixup.

Basically, in C++, const, non-local variables are genuine constant expressions, or constexpr. This permits plenty of things, like TMP.

const int five = 5;
int main() {
    int x[five];
    std::array<int, five> arr;
}

In C, they are just a variable that cannot be modified. That is,

const int five = 5;
int main() {
    int x[five]; // Technically, this is a variable length array
}

Is quite equivalent to

int five = 5;
int main() {
    int x[five];
}

Effectively, C++ promotes some kinds of const variable to a new category, constexpr , whereas in C, this does not exist and they are just variables which happen to be unmodifiable.

Why do English people spell COLOUR, whereas American people spells it COLOR?

They are 2 different languages from the same base, but they don't have the same rules.

C & C++ are the same. If they weren't different, they would both be called the same thing.

My workaround was declaring it as:

static classfoo foo;

it worked in my situation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM