This week.. and sadly the last week.. we were wrapping up the course material. We did a review of the material covered after the second test, in addition to new stuff about manipulators (endl, setw) and other adapters (ptr_fun, mem_fun_ref). We looked into how ostream's operator << is overloaded to account for functions as well. The ptr_fun helps in converting a function into a function object, and similarly mem_fun_ref converts an object's method into a method object. These are helpful where functions like bind2nd are used, as they require a function object as their argument.
It is strange, and I am quite surprised that I would feel nostalgic by the end of this summer session. I guess, it's partly because I am about to leave Austin, and about to start upon a new venture in an entirely different world. Initially, it seemed as if the summer session was to remain forever, and now it appears as if it got finished the moment it started.
By the end of this course, I can definitely say that this course has increased my aptitude for programming, and expanded my understanding of the C++.
Sunday, August 16, 2009
Monday, August 10, 2009
Week 9
This week we work upon the Project 9 - Graph; the task was to reverse engineer the Boost Graph Library and implement a Graph class which will bear the functionality of adding vertices and directed edges. It also provides methods to determine whether the graph is Directed Acyclic Graph (DAG), and if it is, it provide function to topologically sort the vertices. The most daunting task was to have a firm and robust design for the data structure to be used for the implementation. We ended up using a vector of sets, where the index of the vector would determine the vertex, and the corresponding set elements will represent the vertices that are connected to this vertex. As discussed in the class, there are other standard implementation of the graphs: adjacency lists (for graphs that are sparse), and adjacency matrix (for dense graph). Another challenging task was to write the algorithm for the topological sorting. Having done a bit of research, showed that it could be done using depth first traversal. We implemented a recursive function, and a three color scheme to traverse the graph (depth first). The colors determined whether the vertex has been visited, is yet to visit, or has its traversal completed.
In the class, we went over important iterators such as front_insert_iterator (/back_insert_iterator) and their corresponding function objects front_inserter (/back_inserter). These iterators conform to the STL conventions, and could be used with other STL algorithms such as copy. These come in handy when there is a situation such as,
vector x(10,2);
list y(5,3);
std::copy(x.begin(), x.end(), back_inserter(y));
This will result into copying of all the elements of x into y, after which y.size() == 15. However, to have the copy() and other STL algorithms work, the front and back inserters have a peculiar design. The operator *(), operator ++ () return *this of the same type as the class, while operator = (const T& v) also returns itself, but does x.push_front(v) (or x.push_back(v)). A similar design is followed by the ostream_iterator and istream_iterator. However, istream_iterator do maintain data member istream* in to consider the !=EOF criteria.
We learned about few more subtleties of C++ (rather I should say, very important subtleties that if not aware of can lead to programmer's frustration). We studied as to when an argument is taken as a function pointer, and when it's not. For eg.
A x(2,3,4); //constructor
A t; //default constructor
A z(); //function declaration whose return type is A
//LEGAL function declarations
int f(int);
int g(int x); //argument with a name
int h(int (x));
int q((int x)); //ILLEGAL
Likewise, few other examples,
int f(int (*p) ()); //named parameter, with a pointer notation
int g(int p()); //named parameter
int h(int ()); //no name
//all of above mean the same
int m (int (int)); valid
int n (int (int x)); probably unreasonable
In case of ambiguity, the declaration of function wins.
In the class, we went over important iterators such as front_insert_iterator (/back_insert_iterator) and their corresponding function objects front_inserter (/back_inserter). These iterators conform to the STL conventions, and could be used with other STL algorithms such as copy. These come in handy when there is a situation such as,
vector
list
std::copy(x.begin(), x.end(), back_inserter(y));
This will result into copying of all the elements of x into y, after which y.size() == 15. However, to have the copy() and other STL algorithms work, the front and back inserters have a peculiar design. The operator *(), operator ++ () return *this of the same type as the class, while operator = (const T& v) also returns itself, but does x.push_front(v) (or x.push_back(v)). A similar design is followed by the ostream_iterator and istream_iterator. However, istream_iterator do maintain data member istream* in to consider the !=EOF criteria.
We learned about few more subtleties of C++ (rather I should say, very important subtleties that if not aware of can lead to programmer's frustration). We studied as to when an argument is taken as a function pointer, and when it's not. For eg.
A x(2,3,4); //constructor
A t; //default constructor
A z(); //function declaration whose return type is A
//LEGAL function declarations
int f(int);
int g(int x); //argument with a name
int h(int (x));
int q((int x)); //ILLEGAL
Likewise, few other examples,
int f(int (*p) ()); //named parameter, with a pointer notation
int g(int p()); //named parameter
int h(int ()); //no name
//all of above mean the same
int m (int (int)); valid
int n (int (int x)); probably unreasonable
In case of ambiguity, the declaration of function wins.
Sunday, August 2, 2009
Week 8
The week had been full of design making decisions, and most importantly regrets and realizations. I have been working with my partner on the project 7. The project is about implementing a Deque, that would imitate most of the functionality of the standard library's deque (std::deque). We started off with constructors, and tested our deque side by side with the standard deque. Happy with our results, we jumped into coding the methods -- insert, erase, push_front, push_back, etc. Compiling the program without any tests didn't give us any errors/warnings and was a motivation in itself. The realization time started as we started to write the test cases for these methods. Some would result into segfault, and for some the assertions would fail; and some wouldn't even compile. Yet, withstanding all the errors, and resolving those we had our "Deque.h" ready with all of our tests passing. The time was 6:00p on a Sunday (today).
Something struck on us suddenly, the motif behind implementing a deque; shouldn't it have an amortized constant time complexity for push_front() and push_back(). But too late to realize, that we had implemented a vector :(. A few minutes ago I was thinking of all the good stuff I would had for the dinner, and a few minutes later... I could think nothing except the program. But I realized, that some times (or most of the time in my case) when under pressure, brain functions better and productively (though, often it turns into a numb state). And so happened with us, the idea had to click (which hadn't for the whole week) and we had the real deque implemented. Thanks to the partnership again!
Something struck on us suddenly, the motif behind implementing a deque; shouldn't it have an amortized constant time complexity for push_front() and push_back(). But too late to realize, that we had implemented a vector :(. A few minutes ago I was thinking of all the good stuff I would had for the dinner, and a few minutes later... I could think nothing except the program. But I realized, that some times (or most of the time in my case) when under pressure, brain functions better and productively (though, often it turns into a numb state). And so happened with us, the idea had to click (which hadn't for the whole week) and we had the real deque implemented. Thanks to the partnership again!
Sunday, July 26, 2009
Week 7
I spent most of this week, and especially the weekend debugging the Project 6 - Matrix. An apparent simple project, turned out to be only hypothetically simple until I hadn't written the test cases. And as I took a step further to write my first test case to test the constructor, the program failed terribly. Lesson: write test cases as you code the program. The project Matrix is all about using Array class that was been created in the last project, though with a twist; this time Array had to be modified to use allocator's construct/destroy method to create a stack allocated array object. The Matrix, would then be implemented as an Array of Arrays.
The lectures this week, were mostly about containers, and iterators, and how the STL are implemented. The subtleties of C++ during compile time related to various constructors, and assignments didn't make much sense until I ran into the problem of having my Matrix class to work correctly. As it was discussed in the class, the compiler chooses to use a default copy constructor/assignment operation which fails to perform a deep copy for user defined classes. In order to have a deep copy, the programmer is required to explicitly define his/her copy constructor, etc. In context to project Matrix, before I created a copy constructor for the Array, I realized that doing operation such as m[2][3] = y would make m[i][3] = y for all 0 < i < R, where m is the matrix, and R is number of rows. Having developed the copy constructor for the Array overcame the problem.
Besides completing the project, I prepared for the Test #2 for which I read a paper on Unified Modeling Language (UML). It's quite interesting to see how a variety of tools/concepts help people collaborate on a project and successfully execute it.
The lectures this week, were mostly about containers, and iterators, and how the STL are implemented. The subtleties of C++ during compile time related to various constructors, and assignments didn't make much sense until I ran into the problem of having my Matrix class to work correctly. As it was discussed in the class, the compiler chooses to use a default copy constructor/assignment operation which fails to perform a deep copy for user defined classes. In order to have a deep copy, the programmer is required to explicitly define his/her copy constructor, etc. In context to project Matrix, before I created a copy constructor for the Array, I realized that doing operation such as m[2][3] = y would make m[i][3] = y for all 0 < i < R, where m is the matrix, and R is number of rows. Having developed the copy constructor for the Array overcame the problem.
Besides completing the project, I prepared for the Test #2 for which I read a paper on Unified Modeling Language (UML). It's quite interesting to see how a variety of tools/concepts help people collaborate on a project and successfully execute it.
Sunday, July 19, 2009
Week 6
This week we studied a number of STL algorithms, and through them enforced the better understanding of different types of iterators: Input Iterator (II), Output Iterator (OI), Forward Iterator (FI), Bidirectional Iterator (BI), and Random access Iterator (RI). Having studied different algorithms such as: Find, MinElement, Transform, Remove, Reverse, Equal, and Accumulate helped in understanding the conventional concept behind different categories of iterators.
We studied the Vector class, which efficiently develops a heap allocated array of objects. The way Vector accomplishes this is by calling the copy constructor of the underlying object class, in contrast to calling the default constructor and the assignment operator as done by stack allocated array. vector uses allocator (memory) to first allocate memory space for the array to be constructed. The allocated memory space is in raw form. Thereafter, it calls the uninitialized_copy/uninitialized_fill which then calls the construct() method; consequently the copy constructor of the underlying value_type. The construct() method calls the placement version of new:
new (p) value_type(v);
A reverse process is pursued while destructing the vector object. It calls, the destory() which calls the destructor for the underlying datatype. It finally deallocates the memory that it assigned for the vector object.
In the last class we studied about iterator_traits, and how meta information inside the Iterator class can be used to infer the return datatype, which in general is not passed as a function template argument.
As for the project, we have been developing an Array class that would implement stack allocated array object and related operations, and methods. Initially we have been getting segfault when trying to call the non-const version of a method from the const method. We overcome the problem by using const_cast casting.
We studied the Vector class, which efficiently develops a heap allocated array of objects. The way Vector accomplishes this is by calling the copy constructor of the underlying object class, in contrast to calling the default constructor and the assignment operator as done by stack allocated array. vector uses allocator (memory) to first allocate memory space for the array to be constructed. The allocated memory space is in raw form. Thereafter, it calls the uninitialized_copy/uninitialized_fill which then calls the construct() method; consequently the copy constructor of the underlying value_type. The construct() method calls the placement version of new:
new (p) value_type(v);
A reverse process is pursued while destructing the vector object. It calls, the destory() which calls the destructor for the underlying datatype. It finally deallocates the memory that it assigned for the vector object.
In the last class we studied about iterator_traits, and how meta information inside the Iterator class can be used to infer the return datatype, which in general is not passed as a function template argument.
As for the project, we have been developing an Array class that would implement stack allocated array object and related operations, and methods. Initially we have been getting segfault when trying to call the non-const version of a method from the const method. We overcome the problem by using const_cast casting.
Saturday, July 11, 2009
Week 5
What an eventful week! Week contained within "containers," and week's tasks iterated over debugging "iterators" :) I spent most of this week working on the project 4 - Integer. And wow, I must say, I learned a lot. The pair programming paid off again. Having worked with the partner simultaneously on the project, allowed me to learn a lot many new concepts of C++; and most importantly their applications and usage.
The project 4 served as a good recall of elementary arithmetic operations: addition, subtraction, multiplication, and division. The project revolves around arbitrary precision integer operations; and the fun part was to calculate the 30th Mersenne prime number (2^132049 - 1) which is around 40000 digits long. And we had it calculated in less than 20 seconds on a Intel Core 2 Duo 2.2 GHz Processor. The optimization technique was to divide the exponent into some power of 2, and multiply them together to find the original power.
There was a doubt though running through me: what's the modulus x % y, when x is a negative number. For instance, -3 % 5 = ? Should it be 2, or -3. While C++ itself calculates it to be -3, while my understanding (as well as Google's) is it should be a positive number. Oh well, we went with the C++ understanding :)
The project 4 served as a good recall of elementary arithmetic operations: addition, subtraction, multiplication, and division. The project revolves around arbitrary precision integer operations; and the fun part was to calculate the 30th Mersenne prime number (2^132049 - 1) which is around 40000 digits long. And we had it calculated in less than 20 seconds on a Intel Core 2 Duo 2.2 GHz Processor. The optimization technique was to divide the exponent into some power of 2, and multiply them together to find the original power.
There was a doubt though running through me: what's the modulus x % y, when x is a negative number. For instance, -3 % 5 = ? Should it be 2, or -3. While C++ itself calculates it to be -3, while my understanding (as well as Google's) is it should be a positive number. Oh well, we went with the C++ understanding :)
Sunday, July 5, 2009
Week 4
This week we went over important concepts such as specialized templates, stacks vs heap allocations, and function pointers.
Specialized templates provide a way of defining secondary templates that can be useful where a known different (and may more efficient) algorithm is to be used to perform a particular task with a particular data type(s). From compiler's perspective, the way function calls are determined is by following order:
(i) Check if there is a non-template version available for the function call. If one does exist call that.
(ii) If the function call is a templatized version, determine the primary template structure.
(iii) Once the primary template structure is determined, check if there is a secondary template version (a specialized function with the matching signature) is available. If a secondary template is available, call that function, else call the primary templatized function.
During the week, we studied how stack allocated arrays differ from heap allocated ones, and in what ways they are similar. Heap allocation offers the flexibility of allocating memory spaces as per the need, but at the same time the programmer is responsible for tracking the allocated memory, and freeing them appropriately when need be so. A rule of thumb is to have as many delete's as there are new's (with appropriate placements). This ensures that there are no memory leakage. A few conceivable problems with heap allocated arrays can be: not freeing memory after use, deleting the wrong memory address, deleting more than needed.
Next, we started on function pointers which in a sense provides a way of customized function calls. The function pointers, allows function calls via pointers that like any other pointer can be changed to call other function.
This week, and the following week I along with my partner will be working on the Project 4 - Integer. The project involves creating a class that implements Big Integer/Arbitrary Precision operations. The idea is to represent numbers with vector/deque where each element is an individual digit, and perform operations on these digits.
Specialized templates provide a way of defining secondary templates that can be useful where a known different (and may more efficient) algorithm is to be used to perform a particular task with a particular data type(s). From compiler's perspective, the way function calls are determined is by following order:
(i) Check if there is a non-template version available for the function call. If one does exist call that.
(ii) If the function call is a templatized version, determine the primary template structure.
(iii) Once the primary template structure is determined, check if there is a secondary template version (a specialized function with the matching signature) is available. If a secondary template is available, call that function, else call the primary templatized function.
During the week, we studied how stack allocated arrays differ from heap allocated ones, and in what ways they are similar. Heap allocation offers the flexibility of allocating memory spaces as per the need, but at the same time the programmer is responsible for tracking the allocated memory, and freeing them appropriately when need be so. A rule of thumb is to have as many delete's as there are new's (with appropriate placements). This ensures that there are no memory leakage. A few conceivable problems with heap allocated arrays can be: not freeing memory after use, deleting the wrong memory address, deleting more than needed.
Next, we started on function pointers which in a sense provides a way of customized function calls. The function pointers, allows function calls via pointers that like any other pointer can be changed to call other function.
This week, and the following week I along with my partner will be working on the Project 4 - Integer. The project involves creating a class that implements Big Integer/Arbitrary Precision operations. The idea is to represent numbers with vector/deque where each element is an individual digit, and perform operations on these digits.
Sunday, June 28, 2009
Week 3
This week, more than anything else, I realized that never procrastinate. Though, once in a while, every week I do take this resolution of finishing my things (assignments, and projects, etc.) before time, but then... :(
This week most of my focus, outside the class, was on the project 3. The project was about implementing the Gregorian Calendar, and developing a class that supports Date operations such as finding the date after a given number of days, or number of days between two given dates, and similarly related operations. As Professor Downing advised, the initial plan was to just develop a modest code that would pass the basic test cases. But, even the algorithm for converting the date to number of days would fail. Oh, and on Friday was the first exam.
Nevertheless, I would say, the best part of the project was the algorithm and the mathematics behind it to convert days to date and vice-versa, so as to suffice the condition of O(1) time and space requirements. Having figured out the mathematics, we now were facing the not-so-understandable concepts of templates, and references to carry out the operations. While compiling, I came across an error like "no matching function to the call..." and it was quite interesting that the keyword "const" fixed it all. Consequently, the result of all the procrastination + the subtleties of C++ was the extra hours that we had to put to have the code working.
In essence, however, the project was interesting and I learned a lot.
This week most of my focus, outside the class, was on the project 3. The project was about implementing the Gregorian Calendar, and developing a class that supports Date operations such as finding the date after a given number of days, or number of days between two given dates, and similarly related operations. As Professor Downing advised, the initial plan was to just develop a modest code that would pass the basic test cases. But, even the algorithm for converting the date to number of days would fail. Oh, and on Friday was the first exam.
Nevertheless, I would say, the best part of the project was the algorithm and the mathematics behind it to convert days to date and vice-versa, so as to suffice the condition of O(1) time and space requirements. Having figured out the mathematics, we now were facing the not-so-understandable concepts of templates, and references to carry out the operations. While compiling, I came across an error like "no matching function to the call..." and it was quite interesting that the keyword "const" fixed it all. Consequently, the result of all the procrastination + the subtleties of C++ was the extra hours that we had to put to have the code working.
In essence, however, the project was interesting and I learned a lot.
Thursday, June 25, 2009
Pair Programming
This blog entry summarizes the key points of the paper by Laurie A. Williams and Robert R. Kessler which is about Pair Programming. "Pair programming is a style of programming in which two programmers work side-by-side at one computer, continuously collaborating on the same design, algorithm, code or test." It is one of the core practices of eXtreme Progamming (XP).
We as programmers are conditioned to work alone, as we are too much under the impression that thinking independently will allow us to formulate our deeply-concentrated thoughts better. Studies, however, show that pair programming allows us to become more efficient programmers.
The key importance lies in the below mentioned attributes:
1) Continuous code review by person watching over the shoulders
2) Exchange of ideas which could disclose possible flaws, and bring about improvements
3) Efficient, and a greater confidence in the solution
4) High level of code quality which is nearly bug free
5) Enjoyable experience
The paper then talks about the important principles of pair programming. Here are some of those:
SHARE EVERYTHING and PLAY FAIR
Two programmers are assigned to produce one artifact - design, algorithm, or program, etc. Both partners are working actively, even though one is putting the ideas together whether in a code, or in a design on the paper; the other partner on the other hand is continuously reviewing the work. Both are equally creditable or liable.
BEING LESS OF A SLACKER
I realized that I check my Facebook account, and dozens of email accounts quite frequently even though I know I am expecting nothing but tonnes of spams. And when I am saying frequently, I mean it... I mean at least once in every 15-20 minutes. While, working over the past two projects, I realized that I barely check my accounts while I am working with my partner, unless we are taking a break. In essence, I am much more focused and dedicated, and being less of a slacker :).
EXCHANGE OF IDEAS
Honestly, I have learned a lot over the past 3 weeks. The way my partner thinks, motivates me to think differently, allows me to think out of my own little box of ideology. Continuous discussion, and constructive arguments are the best training, I believe.
DON'T TAKE THINGS TOO SERIOUSLY
"Ego-less programming" as the mentioned in the paper, is the key to fully take the advantage of the pair programming. The arguments should be taken as a resource to further hone an individual's programming skills.
WASH YOUR HANDS OFF SKEPTICISM BEFORE YOU START
There should be no scope of skepticism with pair programming; if something looks confusing or non-understandable clarify the doubts. But, trust your partner. Engage in constructive arguments if need be so. One idea is that the outcome of a union of team members is more than the disjoint sets of members, contrary to traditional set theory. As experiences have shown, a pair produces more than twice as many solutions than the two working independently.
FLUSH/REVIEW WORK DONE INDEPENDENTLY
We have other commitments of time and we need to be working on some tasks independently, or just for some deep-concentration thinking. However, it is the best practice to review the work done independently together with your partner; it could possibly disclose a plethora of subtleties.
And finally,
ALL WORK and NO PLAY MAKES everyone dull... so take breaks occasionally.
For cost/benefit analysis of the Pair Programming methodology, I came across a paper by Alistair Cockburn, and Laurie Williams.
We as programmers are conditioned to work alone, as we are too much under the impression that thinking independently will allow us to formulate our deeply-concentrated thoughts better. Studies, however, show that pair programming allows us to become more efficient programmers.
The key importance lies in the below mentioned attributes:
1) Continuous code review by person watching over the shoulders
2) Exchange of ideas which could disclose possible flaws, and bring about improvements
3) Efficient, and a greater confidence in the solution
4) High level of code quality which is nearly bug free
5) Enjoyable experience
The paper then talks about the important principles of pair programming. Here are some of those:
SHARE EVERYTHING and PLAY FAIR
Two programmers are assigned to produce one artifact - design, algorithm, or program, etc. Both partners are working actively, even though one is putting the ideas together whether in a code, or in a design on the paper; the other partner on the other hand is continuously reviewing the work. Both are equally creditable or liable.
BEING LESS OF A SLACKER
I realized that I check my Facebook account, and dozens of email accounts quite frequently even though I know I am expecting nothing but tonnes of spams. And when I am saying frequently, I mean it... I mean at least once in every 15-20 minutes. While, working over the past two projects, I realized that I barely check my accounts while I am working with my partner, unless we are taking a break. In essence, I am much more focused and dedicated, and being less of a slacker :).
EXCHANGE OF IDEAS
Honestly, I have learned a lot over the past 3 weeks. The way my partner thinks, motivates me to think differently, allows me to think out of my own little box of ideology. Continuous discussion, and constructive arguments are the best training, I believe.
DON'T TAKE THINGS TOO SERIOUSLY
"Ego-less programming" as the mentioned in the paper, is the key to fully take the advantage of the pair programming. The arguments should be taken as a resource to further hone an individual's programming skills.
WASH YOUR HANDS OFF SKEPTICISM BEFORE YOU START
There should be no scope of skepticism with pair programming; if something looks confusing or non-understandable clarify the doubts. But, trust your partner. Engage in constructive arguments if need be so. One idea is that the outcome of a union of team members is more than the disjoint sets of members, contrary to traditional set theory. As experiences have shown, a pair produces more than twice as many solutions than the two working independently.
FLUSH/REVIEW WORK DONE INDEPENDENTLY
We have other commitments of time and we need to be working on some tasks independently, or just for some deep-concentration thinking. However, it is the best practice to review the work done independently together with your partner; it could possibly disclose a plethora of subtleties.
And finally,
ALL WORK and NO PLAY MAKES everyone dull... so take breaks occasionally.
For cost/benefit analysis of the Pair Programming methodology, I came across a paper by Alistair Cockburn, and Laurie Williams.
Sunday, June 21, 2009
Week 2
This week, I witnessed a plethora of interesting subtleties of C++:
i) the pointers, and the references;
ii) types of variables
iii) templates
It's interesting how placement of '&' and '*' can give a whole different meaning to variables. For example,
int i = 2;
int* p = j; // does not compile
int* p = &j; /* initializes a pointer 'p' pointing to integer 'j' */
/*increments the memory address which could lead to illegal memory access */
++p;
//increments j
++*p;
Now consider,
int k = 4;
int& r = k; /* r serves as an alias of k */
//same as ++k
++r;
Using '&' for references frees the programmer from de-referencing the variable like in pointers. However, once the reference is defined, it is glued to the variable it references; while the pointer can be changed to point to other variable (if not declared as constant).
Things become interesting when using '&' and '*' together. While, int&* x isn't valid, but
int i = 2;
int* p = i;
int*& r = p; //alias for pointer 'p'
Next, we studied about different types of variables, and compared their scopes, lifetimes, and time-line when they are allocated, and initialized. "non-static local variable" and "static local variable" both differ except in terms of their scope. Contrarily, "non-static global variable" and "static global variable" differ only in their scopes. "Non-static global variable" has the scope of whole program, while "static global variable" has the file scope. The program will compile even if a static variable is used in other file using extern, but will fail during the linkage.
C++ has a powerful feature of creating templates. But with power, comes the responsibility; and here the responsibility is of the programmer to fully understand how to create classes considering the types of variables and their instances to be created. For example,
template <typename T>
struct A {
static T sv0; // creates one sv0 per T
static int sv1; // still creates one sv1 per T
T v0; // create 1 v0 per instance of A
}
Finally, we studied how different function declaration give or don't give access to the original data.
For example,
void f(int v) {++v;} // creates a local copy of the argument
void g(int* p) {++*p;} // changes the original data
void h(int& r) {++r;} // changes the original data
i) the pointers, and the references;
ii) types of variables
iii) templates
It's interesting how placement of '&' and '*' can give a whole different meaning to variables. For example,
int i = 2;
int* p = j; // does not compile
int* p = &j; /* initializes a pointer 'p' pointing to integer 'j' */
/*increments the memory address which could lead to illegal memory access */
++p;
//increments j
++*p;
Now consider,
int k = 4;
int& r = k; /* r serves as an alias of k */
//same as ++k
++r;
Using '&' for references frees the programmer from de-referencing the variable like in pointers. However, once the reference is defined, it is glued to the variable it references; while the pointer can be changed to point to other variable (if not declared as constant).
Things become interesting when using '&' and '*' together. While, int&* x isn't valid, but
int i = 2;
int* p = i;
int*& r = p; //alias for pointer 'p'
Next, we studied about different types of variables, and compared their scopes, lifetimes, and time-line when they are allocated, and initialized. "non-static local variable" and "static local variable" both differ except in terms of their scope. Contrarily, "non-static global variable" and "static global variable" differ only in their scopes. "Non-static global variable" has the scope of whole program, while "static global variable" has the file scope. The program will compile even if a static variable is used in other file using extern, but will fail during the linkage.
C++ has a powerful feature of creating templates. But with power, comes the responsibility; and here the responsibility is of the programmer to fully understand how to create classes considering the types of variables and their instances to be created. For example,
template <
struct A {
static T sv0; // creates one sv0 per T
static int sv1; // still creates one sv1 per T
T v0; // create 1 v0 per instance of A
}
Finally, we studied how different function declaration give or don't give access to the original data.
For example,
void f(int v) {++v;} // creates a local copy of the argument
void g(int* p) {++*p;} // changes the original data
void h(int& r) {++r;} // changes the original data
Sunday, June 14, 2009
Week 1 - CS378
Aah haa, the class had just started and the first week is already over. Oh! And what a class strength, quite contrary to what I expected. The time I was registering for the course, I along with other students was skeptic if we'll have the privilege of continuing with the class. And now, the class is full of inquisitive students, and the interesting interaction with so much to learn. As Professor Downing mentioned, learning is a continuous process.
I have had few programming classes before, but the concepts that I have started to learn from the day 1 of class I had no idea of those before. The fundamentals of l-value and r-value, the return types, and return values are now much more clear. The quizzes that started from the second class helped me a lot to understand the material that was taught in the previous class.
During the first week, we got our first project which was to be done collaboratively with other partner. The first project itself prooved to be an excellent source of learning a whole new paradigm of programming aspects, and software management. It was the first time, I was exposed to Google Projects, and working with subversion and issue tracking. As a part of the project, we were to build the unit test cases as well. I was quite surprised as how assertion and unit cases can disclose some obscure bugs that would otherwise have been so difficult to track and debug.
In the last classes, we learned about formatting, and other subtleties of C++. We started with a topic on throwing exceptions, and we’ll be continuing with it the coming week. I definitely look forward to the following weeks.
I have had few programming classes before, but the concepts that I have started to learn from the day 1 of class I had no idea of those before. The fundamentals of l-value and r-value, the return types, and return values are now much more clear. The quizzes that started from the second class helped me a lot to understand the material that was taught in the previous class.
During the first week, we got our first project which was to be done collaboratively with other partner. The first project itself prooved to be an excellent source of learning a whole new paradigm of programming aspects, and software management. It was the first time, I was exposed to Google Projects, and working with subversion and issue tracking. As a part of the project, we were to build the unit test cases as well. I was quite surprised as how assertion and unit cases can disclose some obscure bugs that would otherwise have been so difficult to track and debug.
In the last classes, we learned about formatting, and other subtleties of C++. We started with a topic on throwing exceptions, and we’ll be continuing with it the coming week. I definitely look forward to the following weeks.
Subscribe to:
Posts (Atom)