Static variable shadowing global - c++

I am trying to create an object using placement new (I know to use smart pointers, this is just to learn). My code is as follows:
#include <vector>
#include <iostream>
#include <memory>
using namespace std; // please excuse this
// if you change like 19 to arr1 (or any other var name) instead of arr and line 40 to arr1 then it works
struct A
{
int in = 999;
A()
{cout << "A ctor\n";}
~A()
{cout << "A dtor\n";}
};
char arr[sizeof(A)];
class B
{
public:
static char arr[sizeof(A)];
const static A* a_obj;
B()
{
cout << "B ctor\n";
//cout << (a_obj->in) << endl;
}
~B()
{
cout << "B dtor\n";
}
};
const A* B::a_obj = new(arr) A;
int main()
{
B g;
}
I have created a global array named arr and another array named arrin B. It seems like when I do my placement new the arr being used is from the class as I get what I think are linker errors.
Why is this happening? why isn't the global arr being used? If i change the placement new to use my renamed global array it works. I think it has to do something with lookups but I don't have a concrete answer.

From the C++ 2017 Standard (12.2.3.2 Static data members)
2 The declaration of a non-inline static data member in its class
definition is not a definition and may be of an incomplete type other
than cv void. The definition for a static data member that is not
defined inline in the class definition shall appear in a namespace
scope enclosing the member’s class definition. In the definition at
namespace scope, the name of the static data member shall be qualified
by its class name using the :: operator. The initializer expression
in the definition of a static data member is in the scope of its
class (6.3.7).
So in this definition of the static data member
const A* B::a_obj = new(arr) A;
the unqualified name arr is at first searched in the scope of the class B. And the class B indeed declares such a name
static char arr[sizeof(A)];
If you want to use the name from the global namespace then use the qualified name
const A* B::a_obj = new(::arr) A;
Here is a demonstrative program
#include <iostream>
struct A
{
const static int N = 10;
static int n1;
static int n2;
};
const int N = 20;
int A::n1 = N;
int A::n2 = ::N;
int main()
{
std::cout << "A::n1 = " << A::n1 << std::endl;
std::cout << "A::n2 = " << A::n2 << std::endl;
return 0;
}
Its output is
A::n1 = 10
A::n2 = 20

The reason arr is attribute to the class B and not the global scope is due to unqualified name lookup rules.
Specifically:
Static data member definition For a name used in the definition of a
static data member, lookup proceeds the same way as for a name used in
the definition of a member function.
Meaning:
struct X {
static int x;
static const int n = 1; // found 1st
};
int n = 2; // found 2nd.
int X::x = n; // finds X::n, sets X::x to 1, not 2
If you are intrested you can see more information here:
http://en.cppreference.com/w/cpp/language/unqualified_lookup
As people suggested to get what you want just use:
const A* B::a_obj = new(::arr) A;

Related

Code displays "::" on the terminal, cause unknown

using namespace std;
struct A
{
int i;
A(int i_ = 13) : i(i_)
{
cout << _FUNCTION_ << "\n";
}
~A()
{
cout << _FUNCTION_ << "\n";
}
};
int main()
{
A* p = new A;
A a();
return 0;
}
When I run it, the code displays on my terminal "A::A". I get that the first A is called from first FUNCTION for "A* p" , but why does "::" appear? And the last A after "::" is from " A a(); "?
A constructor for a type has the same name as the type itself. :: is the scope resolution operator and is used to name things contained within a named scope, such as a namespace or a type.
The constructor of A is therefore A::A. The first A is the name of the type, and the second is the name of the constructor; the :: is to indicate that the constructor is declared within the scope of the type.
This mirrors the way you would define type members following a declaration with no definition. For example:
struct A
{
int i;
A(int i_ = 13);
~A();
};
// Note how we have to refer to the constructor to define it since we are
// no longer within the scope of A:
A::A(int i_) : i(i_)
{
cout << _FUNCTION_ << "\n";
}
// Similar for the destructor.
A::~A()
{
cout << _FUNCTION_ << "\n";
}
You should only see A::A in your output. Note that you only create one A value here:
A* p = new A;
You never delete p; and so you don't see the matching destructor call (A::~A) in the output.
This line does not create a variable of type A; rather, it declares a function called a that takes no arguments and returns an A value. This function is never invoked (nor defined):
A a();
This is a vexing parse (not to be confused with the most vexing parse). Clearly you intended to declare a variable, but this could be either a function or variable declaration, and the grammar prefers a function declaration.
To fix this, either remove the parens or use C++11's uniform initialization syntax:
A a; // Default initialization
A a{}; // Uniform initialization
_FUNCTION_ is a magic constant, therefore it posts the first "A" (name of the function called. Can't help with the rest though.

Why does C++ allow a local variable in class member function to be the same name as a member variable?

Why does C++ allow a local variable in class member function to be the same name as a member variable? What is the benefit of allowing this?
The following code compiles.
class test
{
public:
int i = 4;
void func(){
int i = 5;
cout << i << endl;
cout << this->i << endl;
}
};
int main(int argc, char const *argv[])
{
test t;
t.func();
}
The output is
5
4
I don't think there's any undefined behavior going on here so it seems the standard allows this.
I just spent an hour debugging a code where I accidentally used the following in a class member function
auto member_var_name = some_val; // declared and defined a local variable with the same name as the class member variable
when I meant to just do
member_var = some_val;
I did know that constructors could use class member names as parameter names, but I didn't know something like this was allowed as well.

If multiple classes have a static variable in common, are they shared (within the same scope?)

I have the following example code:
class A {
public:
static int a;
};
int A::a = 0;
class B {
public:
static A a1;
};
A B::a1;
class C {
public:
static A a1;
};
A C::a1;
int main(int argc, const char * argv[]) {
C::a1.a++;
B::a1.a++;
std::cout << B::a1.a << " " << C::a1.a << std::endl;
return 0;
}
Class B and C have class A as a static member variable.
I expected the program to print "1 1", however it prints "2 2".
If multiple classes have a static variable in common, are they shared (within the same scope?)
The static members belong to class, it has nothing to do with objects.
Static members of a class are not associated with the objects of the class: they are independent objects with static storage duration or regular functions defined in namespace scope, only once in the program.
For your code, there's only one A::a, which is independent of B::a1 and C::a1 (which are objects of class A). So both B::a1.a and C::a1.a refer to A::a.
You're not looking at multiple classes here. Both B::a1 and C::a1 are of type A. And A has a static variable a, that you accessed twice. If you also wrote A::a++, your program would have printed 3 3
To modify your example slightly:
struct A
{
static int a;
int b;
};
int A::a;
struct B
{
static A a1;
};
A B::a1{0};
struct C
{
static A a2;
};
A C::a2{0};
and the user code:
B::a1.a = 1; // A's static variable changed
B::a1.b = 2; // B's A's b changed to 2
cout << B::a1.a << ", " << B::a1.b << endl;
cout << C::a2.a << ", " << C::a2.b << endl;
It will print:
1, 2
1, 0
That's because all As share a, but all As have their own b. And both C and B have their own A (that they respectively share between objects of their type)
B and C both have static instances of A, these are seperate instances of A and would have different seperate instances of it's members as well. However, A::a is a static variable that is shared between all instances of A so:
&B::a1 != &C::a1 (the two a1 are seperate)
but
&B::a1.a == &C::a1.a (i.e. all A::a are the same, no matter the 'enclosing' instance of A)

Order of evaluation of names declared in class

There is this code:
#include <iostream>
const int c = 3;
struct A {
static int f() { return c; }
static const int c = 2;
};
int main() {
std::cout << A::f() << std::endl; // 2
return 0;
}
How does it happen that variable c defined inside class A is used in function f instead of variable c defined in global scope although global variable c is declared first?
It does not matter which variable is declared first: if a class has a variable with the same name in it, that variable trumps the global variable. Otherwise you could get existing code in a lot of trouble simply by declaring a global variable with a name of one of its member variables!
Of course your class can use scope resolution operator to reference the global c directly:
static int f() { return ::c; }
Now your program will print 3 instead of 2.
Is not a question of declaring order but of variable scope, the used variable are searched before in the current method/function after in the class/struct and a the and in the global context,
example:
#include <iostream>
const int c = 3;
struct A {
static void print() {
int c = 4
std::cout <<"Method Scope:"<< c << std::endl; // 4
std::cout <<"Class/Struct Scope:"<< A::c << std::endl; // 2 here you can use alse ::A::c
std::cout <<"Global Scope:"<< ::c << std::endl; // 3
}
static const int c = 2;
};
struct B {
static void print() {
std::cout <<"Method Scope:"<< c << std::endl; // 2
std::cout <<"Class/Struct Scope:"<< B::c << std::endl; // 2 here you can use alse ::A::c
std::cout <<"Global Scope:"<< ::c << std::endl; // 3
}
static const int c = 2;
};
struct C {
static void print() {
std::cout <<"Method Scope:"<< c << std::endl; // 3
//std::cout <<"Class/Struct Scope:"<< C::c << std::endl; //is inpossible ;)
std::cout <<"Global Scope:"<< ::c << std::endl; // 3
}
};
int main() {
A::print();
B::print();
C::print();
return 0;
}
imagine that you have long code which uses many variables, do you want them to be called instead these from a class to which function belongs? stating:
a or b
in class means
this->a
this->b
and if you want global variable to be visible you have to use it like
::a or ::b inside this function, so via:
static int f() { return ::c; }
From the standard docs, Sec 3.3.1
Every name is introduced in some portion of program text called a declarative region, which is the largest part of the
program in which that name is valid, that is, in which that name may be used as an unqualified name to refer to the
same entity. In general, each particular name is valid only within some possibly discontiguous portion of program text
called its scope. To determine the scope of a declaration, it is sometimes convenient to refer to the potential scope of
a declaration. The scope of a declaration is the same as its potential scope unless the potential scope contains another
declaration of the same name. In that case, the potential scope of the declaration in the inner (contained) declarative
region is excluded from the scope of the declaration in the outer (containing) declarative region.
this means that the potential scope is same as the scope of the declaration unless another (inner) declaration occurs. If occurred, the potential scope of the outer declaration is removed and just the inner declaration's holds, so your global variable is hidden.

member variable

Can there be a member variable in a class which is not static but which needs to be defined
(as a static variable is defined for reserving memory)? If so, could I have an example? If not, then why are static members the only definable members?
BJARNE said if you want to use a member as an object ,you must define it.
But my program is showing error when i explicitly define a member variable:
class test{
int i;
int j;
//...
};
int test::i; // error: i is not static member.
In your example, declaring i and j in the class also defines them.
See this example:
#include <iostream>
class Foo
{
public:
int a; // Declares and defines a member variable
static int b; // Declare (only) a static member variable
};
int Foo::b; // Define the static member variable
You can now access a by declaring an object of type Foo, like this:
Foo my_foo;
my_foo.a = 10;
std::cout << "a = " << my_foo.a << '\n';
It's a little different for b: Because it is static it the same for all instance of Foo:
Foo my_first_foo;
Foo my_second_foo;
Foo::b = 10;
std::cout << "First b = " << my_first_foo.b << '\n';
std::cout << "Second b = " << my_second_foo.b << '\n';
std::cout << "Foo::b = " << Foo::b << '\n';
For the above all will print that b is 10.
in that case, you would use the initialization list of test's constructor to define the initial values for an instance like so:
class test {
int i;
int j;
//...
public:
test() : i(-12), j(4) {}
};
That definition reserves space for one integer, but there'll really be a separate integer for every instance of the class that you create. There could be a million of them, if your program creates that many instances of test.
Space for a non-static member is allocated at runtime each time an instance of the class is created. It's initialized by the class's constructor. For example, if you wanted the integer test::i to be initialized to the number 42 in each instance, you'd write the constructor like this:
test::test(): i(42) {
}
Then if you do
test foo;
test bar;
you get two objects, each of which contains an integer with the value 42. (The values can change after that, of course.)