+ 43

[BLOG] C++ Bread && Butter (Part 1)

Part 1: Variables 1-1: Naming conventions (Good old advices) 1-2: Variable initialization (Don't mix up!) 1-3: Scope of variables (I can't see upstairs!) 1-4: Global variable madness! 1-5: My variable has auto type! 1-6: "auto" makes your life easier Dear friends, Please send your comments, questions, suggestions, feedbacks, and criticisms to [https://www.sololearn.com/Discuss/683525/c-bread-butter-q-a] Many thanks for your understanding. ;)

3rd Sep 2017, 4:54 PM
Babak
Babak - avatar
12 Respostas
+ 25
1-2: Variable initialization (Don't mix up!) In C++, There are 3 ways to initialize variables: 1.The first one, known as "C-like initialization". (inherited from good old days) format: dataType idName = initialValue; [e.g. int foo = 7;] --------------------- 2. The second one, known as "constructor initialization". format: dataType idName (initialValue); [e.g. int foo (7);] --------------------- 3. The third one, known as "uniform initialization".(introduced by C++11) format: dataType idName {initialValue}; [e.g. int foo {7};] https://code.sololearn.com/c8hRdDAmlZoe
3rd Sep 2017, 2:59 PM
Babak
Babak - avatar
+ 22
1-3: Scope of variables(I can't see upstairs!) • Scope: The portion of the program where a variable can be visible and used is known as its scope. For example,a variable can be visible to a block (a section of code enclosed in curly braces), a routine, a class, or the whole program. • Local & Global scopes: A variable defined inside a particular code unit is said to be a "local variable" relative to that code unit. Conversly, a variable defined outside a particular code unit is a "global variable" relative to that code unit. https://code.sololearn.com/cf5af71HUwSh • nested scope: Scopes can contain other scopes. The contained (or nested) scope is referred to as an "inner scope", the containing scope is the "outer scope". >> 70% Pitfall: Which cout prints which variable? ///////////////////// #include <iostream> int main() { int n = 2; std::cout << n << endl; // output: 2 if (n > 0) { int n = 5; std::cout << n << endl; // output: 5 if (n == 5) std::cout << n << endl; // output: 5 } std::cout << n; // output: 2 } ///////////////////// https://code.sololearn.com/cW84G16f37vn This is called a "name-hiding" issue. As a "rule", C++ always use the variable "closest" to the working code unit. Therefore, avoid variable names that hide names in outer scope(s). (same name in each scope) • Scope resolution operator: There are some uses for scope resolution operator "::". One of which related to access to a global variable when there is a local variable with the same name. ////////////// #include <iostream> int n = 1000; int main() { int n = 2; std::cout << n << endl; // output: 2 if (n > 0) { int n = 5; std::cout << n << endl; // output: 5 if (n == 5) std::cout << ::n << endl; // output: 1000 } std::cout << n; // output: 2 } //////////////// https://code.sololearn.com/c7vyMeL1egYL
3rd Sep 2017, 2:59 PM
Babak
Babak - avatar
+ 21
1-1: Naming conventions (Good old advices) There are a number of "generally" accepted conventions for naming variables. Following these conventions can improve the readability of a program. • An identifier [e.g. variable name, function name etc] should give some indication of its meaning. • Variable names normally are lowercase. [e.g. "result", not Result or RESULT] • classes and constants you define usually begin with an uppercase letter. [e.g. "class Spaceship" or "const double Pi = 3.14159265"] • Identifiers with multiple words should visually distinguish each word. [e.g. "interest_rate(Pascal case)" or "interestRate(Camel case)", not interestrate] >> 100% tip: Try to avoid using "single and double underscore at the begining" of an identifier name. Why? Because, when naming an identifier, you want to avoid collision with compiler reserved names, operating system routines, and standard library. Also, it is a good practice to have a portable code to run on different compilers with different versions. So, Don't bother compiler and people! and, 1. Never start your identifier name with an underscore. [e.g. int _xy = 0; // Bad int x_y = 0; // Good int xy_ = 0; // Good int x_y_ = 0; // Good int _x_y = 0; // Bad int _xy_ = 0; // Bad int _x_y_ = 0; // Bad ] 2. Never use two consecutive underscore nowhere in your identifier name. [e.g. int __xy = 0; // Bad int x__y = 0; // Bad int xy__ = 0; // Bad int __xy__ = 0; // Bad ]
3rd Sep 2017, 2:59 PM
Babak
Babak - avatar
+ 21
1-4: Global variable madness! Somebody asked the guru what's the best naming prefix for a global variable? The guru said " // " Anyway! >> 90% pitfall: But why? • Side effect problem: You might change the value of a global variable in one place and mistakenly think that it has remained unchanged somewhere else. (e.g. Leads to a unexpected program flow) https://code.sololearn.com/ct1HRJfaxpRP • Aliasing problems: Aliasing refers to calling the same variable by two or more different names. This happens when a global variable is passed to a routine and then used by the routine both as a global variable and as a parameter. /////////////////////// #include <iostream> int gVar; // Global void funksion(int &input) { input = 10; gVar = input + 5; std::cout << "input = " << input << endl; // input = 15 std::cout << "gVar = " << gVar << endl; // gVar = 15 } int main() { gVar = 30; funksion(gVar); } //////////////////////// You see, input and gVar are the same variables. cout prints a variable twice, even though they refer to two different names. https://code.sololearn.com/cmAONio164sk • Damage to program modularity: $ What do you mean by modularity? The essence of creating programs that are larger than a few hundred lines of code is managing complexity. The only way you can intellectually manage a large program is to break it into pieces so that you only have to think about one part at a time. Modularization is the most powerful tool at your hand for breaking a program into pieces. $ So what?! Global data pokes holes in your ability to modularize. If you use global data, can you concentrate on one routine at a time? No. You have to concentrate on one routine and every other routine that uses the same global data. Although global data doesn’t completely destroy a program’s modularity, it weakens it, and that’s reason enough to try to find better solutions to your problems.
3rd Sep 2017, 3:00 PM
Babak
Babak - avatar
+ 20
1-6: "auto" makes your life easier • Using auto in Range-Based for Statement: Wait a sec! First, tell me about range-based for loop. I've never heard it before! A common use of the for statement is to iterate over a container of elements (e.g. array, string, vector, map etc). Currently, the syntax for built-in arrays and library containers is different (built-in arrays use an index or raw pointers, and container classes use iterators (**Don't forget to tell me about iterators later!) returned by the "begin" and "end" member functions.) In addition to providing simpler syntax, the new range-based for statement allows you to use the same syntax for iterating over both arrays and containers. ///////////////////// #include <iostream> int main() { int arr[] = {1,2,3,4,5}; for (auto x : arr) std::cout << x; } ///////////////////// https://code.sololearn.com/cHrg1B8n78tj So, How does it work? In this case, you use auto to let the compiler determine the type of x, which in this case will be int. On each iteration, the next number in arr[] will be copied into x. Thus, you can read this loop as saying, “For every number x in the int arr[],” do something. The “something” in this case is printing the numbers. >> 100% tip: If you want to change the value of the elements in arr[], you must define the loop variable as a "reference type". (Remember that a reference is just another name for a given object). When you use a reference as your control variable, that variable is "bound" to each element in the sequence in turn. Using the reference, you can change the number to which the reference is bound. ///////////////////// #include <iostream> int main() { int arr[] = {1,2,3,4,5}; for (auto &x : arr) std::cout << ++x; }
3rd Sep 2017, 3:00 PM
Babak
Babak - avatar
+ 20
>> 100% tip: But if you just want to read the value of the elements in arr[], it is Preferred to define the loop variable as a "constant reference". (Secure coding) //////// #include <iostream> int main() { int arr[] = {1,2,3,4,5}; for (const auto &x : arr) // read-only std::cout << x; } ///////// https://code.sololearn.com/cJsUa4uFFSg1 **Fasten your seatbelts! We are passing through STL, now! > NOTICE: This is just scrach the surface of STL. The guru promised me to tell me more about that in the near future! • Take a very brief look at the STL vector: A vector is a collection of "objects", all of which have the same type (same as arrays). Every object in the collection has an associated index, which gives access to that object (again, same as arrays). A vector is often referred to as a container because it “contains” other objects. To use a vector, you must include the appropriate header file. (Vectors have many advantages over arrays. You'll see!) ////////// #include <vector> int main() { // An empty integer vector std::vector<int> vec1; // A vector with 10 integer elements std::vector<int> vec2(10); // A vector with 10 integer elements, each having the value 100 std::vector<int> vec3(10, 100); // A list-Initialized vector with 5 integer (C++11) std::vector<int> vec4 = {10,20,30,40,50}; } ////////// $ Well, how can I read/write to each element of a vector? There are two choices in front of you: 1. Using traditional index-based for loop (No problem at all) Or range-based for loop https://code.sololearn.com/cPAtzjF7HJiJ
3rd Sep 2017, 3:02 PM
Babak
Babak - avatar
+ 19
The same person asked the guru if global variables are so EVIL Why do we care about them? The guru said "Because we need them" So convincing! >> 10% benefit: That's really it! • Performance: Global variables increase performance because they can be accessed directly by any function so, the overhead of passing data to functions is eliminated.(But is it really worth it?) 1-5: My variable has auto type! Wow! Another cool feature. Can't wait, tell me about it real quick! It is not uncommon to want to store the value of an expression in a variable. To declare the variable, you have to know the type of that expression. When you write a program, it can be surprisingly difficult (and sometimes even impossible) to determine the type of an expression. Under the new standard (C++11), you can let the compiler figure out the type for you by using the "auto" type specifier. Unlike type specifiers, such as double (that name a specific type), auto tells the compiler to "deduce" the type from the initializer. https://code.sololearn.com/cZL2piV6OPHf >> 25% tip: By implication, a variable that uses "auto" as its type specifier must have an "initializer". auto supports the declaration of multiple variables in one statement [e.g. auto a = 10, b = 20;]. The initializers for all the variables in the declaration must have types that are consistent with each other. [e.g. auto i = 0, *p = &i; // ok: i is int and p is a pointer to int auto s = 0, pi = 3.14; // error: inconsistent types for s and pi ] >> 15% tip: The auto keyword is meant to save time and ease the learning process. >> 10% tip: auto can also be used with const. [e.g. const auto E = 2.7182;]
3rd Sep 2017, 3:00 PM
Babak
Babak - avatar
+ 19
4. dereference the current element of vec4 in each cycle. • Using auto in iterators (Oh boy, you found the missing peace!): When writing above code, you should be getting slightly annoyed. The variable itr is of the exact same type as the expression vec4.begin() with which it is being initialized, and the compiler knows what that type is. Therefore, for us to have to write std::vector<int>::iterator is redundant.Let's cut off the iterator length! ///////////////////// #include <iostream> #include <vector> int main() { std::vector<int> vec4 = {10,20,30,40,50}; for (auto itr = vec4.begin(); itr != vec4.end(); ++itr) st::cout << *itr << " "; } ///////////////////// https://code.sololearn.com/cPoNoo7Wvph9 +-------------+ End of Part 1 +-------------+
8th Sep 2017, 4:02 AM
Babak
Babak - avatar
+ 18
2. Using iterators Although you can use subscripts to access the elements in a vector, there is a more general mechanism—known as iterators—that you can use for the same purpose. Like pointers, iterators give you indirect access to an object. In the case of an iterator, that object is an element in a container. We can use an iterator to fetch an element and iterators have operations to move from one element to another. (Sounds fancy! Tell me how to use it) Unlike pointers, you do not use the address-of operator "&" to obtain an iterator. Instead, types that have iterators (like vectors) have members that return iterators. In particular, these types have members named "begin()" and "end()". The begin() member returns an iterator that denotes the first element, if there is one. (Will discuss in more depth in future parts. I trust the guru!) //// #include <iostream> #include <vector> int main() { std::vector<int> vec4 = {10,20,30,40,50}; // b denotes the first element in vec4 auto b = vec4.begin(); // e denotes one past the last element in vec4 auto e = vec4.end(); std::cout << *b << " " << *(e-1); // Output: 10 50 } //// https://code.sololearn.com/csh3800ukrwD Finally, you are ready to see the mighty iterator! In fact, its structure is similir to a for loop. So, here we go! //// #include <iostream> #include <vector> int main() { std::vector<int> vec4 = {10,20,30,40,50}; for (std::vector<int>::iterator itr = vec4.begin(); itr != vec4.end(); ++itr) cout << *itr << " "; } //// https://code.sololearn.com/cz7D5BObJOE5 Phew! Would you mind to explain the structure a bit more?! Let's breaking it down. for ( 1. std::vector<int>::iterator itr = vec4.begin(); 2. itr != vec4.end(); 3. ++itr ) 4. cout << *itr << " "; 1. declare an iterator called itr of type integer vector and initialize it to the first element of vec4. 2. As a regular for loop, here is a condition. 3. iterator steps
8th Sep 2017, 3:58 AM
Babak
Babak - avatar
+ 10
Wow, brilliant!!! 👏👏👏👆👆👆
3rd Sep 2017, 3:12 PM
dρlυѕρlυѕ
dρlυѕρlυѕ - avatar
+ 7
@Babak Thank you, for sharing!
3rd Sep 2017, 4:58 PM
Manual
Manual - avatar
+ 4
@babak sir thank you so much for this wonderful information
10th Nov 2017, 5:05 AM
Randeep Singh
Randeep Singh - avatar