Hi I am switching to C++ from C. While reading http://www.gotw.ca/publications/xc++.htm I see this code block.
const int i = 1;
const int j = 2;
struct x
{
int x;
};
namespace y
{
int i[i];
int j = j;
x x;
int y::y = x.x;
};
And I am totally confused about this specially in namespace y section.
Please explain me the behavior of this code and use of namespace. Also I read somewhere that bad use of namespace leading to violating fundamentals of inheritance. Please give me some examples of using namespace brilliantly.
This example is using some horribly obfuscated code to illustrate a point about the scope of names. From C++11 §3.3.6 [basic.scope.namespace] p1:
... A namespace member name has namespace scope. Its potential scope includes its namespace from the name’s point of declaration (3.3.2) onwards ...
point of declaration is defined in §3.3.2 [basic.scope.pdecl] p1:
The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below.
So it is possible to use e.g. the name i from an outer scope in the initializer of something named i in an inner scope. The code in question:
const int i = 1;
const int j = 2;
struct x
{
int x;
};
namespace y
{
int i[i];
int j = j;
x x;
int y::y = x.x;
}
declares:
y::i as an array of 1 int that will be implicitly zeroed (since all static storage duration objects are zero-initialized if they have no explicit initializer),
y::j as an int with initial value 2,
y::x as struct of type ::x that will be implicitly zeroed, and
y::y is an invalid name. If it was simply y, it would be an int with initial value 0, since its initializer y::x.x is implicitly zero-initialized.
Here's a demo (with y::y changed to y) at Coliru.
NOTE: DO NOT EVER WRITE CODE LIKE THIS. The only time using this feature of names even borders on being acceptable is for member initializers in a class constructor. If you do this anywhere else, I will find you. And I will make you pay.
I think there is some problem with your code. The int y::y = x.x; section is wrong as there is no y previous to this and so this statement needs some correction. I am trying to give some basic info about namespace and its usage, hope it helps.
The main purpose of namespaces is to logically group functionality without the need of long names and the option for handy usage via "using". You can also use same name over different namespaces
namespace Color
{
class Add {};
class Multiply {};
};
namespace Dimension
{
class Add {};
class Multiply {};
};
So you can use the same class name Add, Multiply under two namespaces and one thing which you have to remember is that use namespaces only when required otherwise you will spam the global namespace "std" unknowingly which is not conventional.
For using namespace with inheritance you can search for articles in stack over flow and definitely you will get some. Ex: Accessing Parent Namespace in C++
int i[i]; //line 1
It creates an int array of size 1, as the index i is a constant initialized to 1
int j = j; //line 2
It declares and initilizes a variable j to 2(value of constant j) in a namespace y
x x; //line 3
It creates a structure variable x of type struct x ( Note: The structure variable x is different from the int x present inside the structure x, int x is a member of structure x
int y::y = x.x; //line 4
This is syntactically wrong, there is no need to qualify int y with namespace('y'), as it is already present in the namespaace y, So the statement should be
int y = x.x
where x.x represents accessing the data member (int x) of structure variable x created in the line 3
Namespace example Have a look on this example,it helps you to understand namespaces clearly. Refer the link for more examples [link]http://www.cplusplus.com/doc/tutorial/namespaces/
#include <iostream>
using namespace std;
namespace first
{
int x = 5;
int y = 10;
}
namespace second
{
double x = 3.1416;
double y = 2.7183;
}
int main () {
using namespace first;
cout << x << endl;
cout << y << endl;
cout << second::x << endl;
cout << second::y << endl;
return 0;
}
//Output
5
10
3.1416
2.7183
......Hope it helps you....:)
Related
This question already has answers here:
variable declaration within the while loop C/C++
(5 answers)
Closed 5 years ago.
Why does this code cause an infinite loop:
#include <iostream>
using namespace std;
int main() {
int y = 5;
while (y < 6) {
int y = 7;
cout << y << endl;
}
}
yet removing the "int" in the while statement makes it run once normally?
(
#include <iostream>
using namespace std;
int main() {
int y = 5;
while (y < 6) {
y = 7;
cout << y << endl;
}
}
)
In this loop:
while (y < 6) {
int y = 7;
cout << y << endl;
}
The inner y is not accessible in the condition test.
If you remove the int in the loop, you're simply assigning a new value to the variable defined outside while, thus terminating it.
Look up Scope on CppReference.
The behaviour you have observed is called shadowing.
This means that a variable is "shadowed" by another variable in an inner scope.
(iBug has already provided a link to the C++ scope rules)
The outer scope (in your case while(y < 6)) can not access the inner scope (in your case int y = 7;) and vice versa. Both have the same name, but they are completely separate variables in separate scopes.
This is a very common source for errors (you also find a lot of them here) and doesn't only happen with loops and other scope brackets, but also very often with class members. Imagine a class:
class MyClass {
int a;
public:
void getA( int a ) { return a; }
};
getA() defines a parameter a, which shadows the class member a. This is at least bad style, but even more probable a source of errors. We don't know - did you want to return the member a or did you really mean the parameter? So this should be avoided.
Here's a real life example on Stackoverflow - see my comment below the question (regarding the 3rd constructor)
Possibilities to avoid these kind of errors are:
Use highest possible compiler warnings and perhaps even warnings as errors. Compilers can warn about those kind of shadowing issues.
Use a name scheme. A common scheme is members with a m, m_ prefix, a _ suffix and the like. If the member name in the MyClass would have been m_a, this would have reduced confusion. Of course this doesn't help in your example, but it's a good idea nevertheless.
This code compiles, but I have a run time error in Visual Studio:
Run-time check failure #3 - the variable 'x' is being used without being initialized...
int x = 15;
int main()
{
int x = x;
return 0;
}
I don't understand that behavior... in the error box when I click continue the program resumes and x has a corrupted content (like -8556328 instead of 15).
Why does this code work without a problem, and the int array is well declared?
const int x = 5;
int main()
{
int x[x] = {1,2,3,4};
return 0;
}
x is defined at the left of =.
so in x[x], [x] refer to the global one,
whereas in x = x;, x hides the global x and initializes from itself -> UB.
When you declare a new variable, its name becomes visible right here
int x =
// ^- there
because it is at that point the variable is fully declared, and as such; its name means something. At this point in time any other (previously declared variable) in a surrounding scope will be hidden.
There is no scope resolution operator in C, so you may not be able to use
int x = x;
in your program.
please use SRO( Scope resolution operator ::) to tell compiler which x is real x in your mind. As user defined names are mangled( Names are decorated) something like this to avoid ambiguity at it's level, these are just names used by compiler that best suits it
int x = 15;// Real name = gui_x
int main()
{
int x = x;// lui_x
return 0;
}
In this way run-time will know which version you are using but to avoid ambiguity it expects from you to use specific names. Sometimes above problem arise where you don't know that you are using already used names. For this C++ has created SRO.
Now in case of array x is address & not integer that stores something, that's why compiler didn't jumbled. You need to write
namespace abc //now all global variables are belongs to this ns abc
int x = 15;// Real name = gui_x
int main()
{
int x = abc::x;// lui_x
return 0;
}
Why isn't the output 101 while I assigned the previous x to the new x?
int x = 101;
{
int x = x;
std::cout << x << std::endl;
}
Output (garbage):
422634
I thought the second x would be initialized to 101 but it isn't initialized.
Note: The solution in this case is int x = ::x but the question is why it happens.
Point of declaration
The point of declaration for a name is immediately after its complete
declarator and before its initializer... [C++ Standard § 3.3.2/1]
Compiler completes the declaration when it knows enough about declarator.
Above code is equal to the below one:
int x = 101;
{
int x;
x = x; <------------------// Self assignment, assigns an indeterminate value.
std::cout << x << std::endl;
}
Because, the declaration of inner x completed before = (assignment)
int x = x; <--// Now, we have the new `x` which hides the older one,
^ // so it assigns itself to itself
|
+---// Point of declaration,
// here compiler knows everything to declare `x`.
// then declares it.
On the other hand, when we declaring complex objects, the point of declaration is farther. So, the behavior is different.
For example, below code is OK
const int i = 2;
{
int i[i];
^
|
+----// Point of declaration
// compiler has to reach to "]"
// therefore before declaring `i` as an array
// there is just one `i`, the `i` of `const int i=2`
}
In above code, compiler has to know the actual size of the array to complete the declaration, so the point of declaration is ]. Therefore the i within [i] is the outer i because declaration of the i of int i[... isn't completed yet. Thus, it declares an array with 2 elements (int i[2];).
Also, this example shows the point of declaration for an enumerator
const int x = 12;
{
enum { x = x };
^
|
+---// Point of declaration
// compiler has to reach to "}" then
// there is just one `x`, the `x` of `const int x=12`
}
The enumerator x is initialized with the value of the constant x, namely 12.
There's another way to do it.
#include <iostream>
int x = 101;
int main()
{
int x = ::x;
std::cout << x << std::endl;
std::cin.get();
}
variable scope
In front of x will be overwritten.
int x = x;
This one there are two processes.
One: int x;(define variable x and allocate memory and specify the initial value : x = 0);
this moment , the front x will be hidden.
Two: x = x;(Do not find the value x);
how does it work? are the variables stored in special registers or memory? im looking at the register/memory windows in visual but i cant understand it :(
#include <iostream>
using namespace std;
namespace first
{
int x = 5;
int y = 10;
}
namespace second
{
double x = 3.1416;
double y = 2.7183;
}
int main () {
using first::x;
using second::y;
cout << x << endl;
cout << y << endl;
cout << first::y << endl;
cout << second::x << endl;
return 0;
}
class CRectangle {
int x, y;
public:
void set_values (int,int);
int area (void);
private:
int param;
} rect;
From the machine's perspective, there's nothing different about private or namespace. Those are just identifiers for the compiler. That is, the compiler enforces access rules, which is why you get compiler errors for doing something you shouldn't. The binary code the compiler ultimately produces, however, doesn't make any distinction about what the data is.
The compiler takes
namespace first
{
int x = 5;
int y = 10;
}
namespace second
{
double x = 3.1416;
double y = 2.7183;
}
and effectively produces assembly code which works something like this:
_first##x: dd 5
_first##y: dd 10
_second##x: dq 3.1416
_second##y: dq 2.7183
In case you are not familiar with assembly language, these four statements each reserve memory, two for 32-bit integers, and two for a floating point values, and assign labels to them. A label is a memory address.
Note that the namespace qualifies each variable name. The # in itself it has no meaning, but escapes the namespace and variable name to isolate unusually named C++ language variables. Assembly language identifiers typically allow a greater range of characters in them than high level languages, convenient in usages such as this.
Namespaces are used as direction for compiler, as actual var names and method/class names have different name after compilation, so namespace name is not used.
I am taking a C++ practice test and I'm confused with a set of access scope and point of declaration related questions. Both the questions are related to each other..I know the answers..what i need is proper explanation :
What is the value of the local variable x at the end of main
int x = 5;
int main(int argc, char** argv)
{
int x = x;
return 0;
}
ans: Undefined
What is the value of y at the end of main?
const int x = 5;
int main(int argc, char** argv)
{
int x[x];
int y = sizeof(x) / sizeof(int);
return 0;
}
answer: 5
From the standard: 3.3.1 [basic.scope.pdecl]
The point of declaration for a name is immediately after its complete declarator (clause 8) and before its initializer (if any), except as noted below.
The standard even has two examples to clarify this:
int x = 12;
{ int x = x; }
Here the second x is initialized with its own (indeterminate) value.
[Note: a nonlocal name remains visible up to the point of declaration of the local name that hides it. [Example:
const int i = 2;
{ int i[i]; }
declares a local array of two integers. ]]
These two examples cover the two cases in your question.
It's controlled by when the inner x comes into existence (the start of its scope). The standard states (3.3.1 in the current standard, 3.3.2 in the upcoming one) in part (my italics):
The point of declaration for a name is immediately after its complete declarator and before its initializer.
With int x = x;, it's created at the point of the = so that when you assign x to it, that's the inner x which is being used. Since that hasn't been set to anything before, it's undefined.
With int x[x];, the inner x comes into existence at the ; so it's using the outer x as the array size.