Dan
Dan

Reputation: 2886

What happens if the same static member variable has different values

1.cc

struct foo{
  const static int bar = 5;
};

int main(){
 return foo::bar;
}

2.cc

struct foo{
  const static int bar = 6;
};

g++ 1.cc 2.cc doesn't give a link error. Does this go against the one definition rule and cause undefined behaviour?

Additionally i'm not sure why const int foo::bar; was not even needed as suggested by this article: https://www.ibm.com/docs/en/zos/2.1.0?topic=members-static-data which says:

Note that the constant initializer is not a definition. You still need to define the static member in an enclosing namespace.

But mine compiles with or without it.

Upvotes: 2

Views: 115

Answers (1)

Artyer
Artyer

Reputation: 40891

You are breaking the One Definition Rule: Class definitions in multiple translation units have to be the same. This makes your program ill-formed, but compiler's don't have to warn you about it.

If you had multiple definitions (const int foo::bar;), you would probably run into a linker error. But without any definitions, it is difficult for the compiler to detect this at link time, so it just isn't.

In practice, if you had a definition in 1.cc, you would find that usages in 1.cc would always evaluate to 5, and in 2.cc they would sometimes be 6 (always 6 in constant expressions) and sometimes be 5.


The reason you don't need a definition to have return foo::bar; is that this does not ODR-use foo::bar, it is simply a constant expression that evaluates to 5 (without needing a definition of foo::bar). If you instead had something like:

int copy(const int& x) {
    return x;
}

int main() {
    return copy(foo::bar);
}

Binding the reference const int& x would ODR-use foo::bar, and the linker would complain about there not being a definition for foo::bar.

Upvotes: 3

Related Questions