We wish to examine our stack and count the number of occurrences of a given character. We can repeatedly pop the stack, testing each element in turn, until the stack is empty. But what if we want to preserve the contents of the stack? Call-by-value parameters accomplish this:
int cnt_char(char c, ch_stack s){
int count = 0;
while (!s.empty())
count += (c == s.pop());
return count;
}
Code Explanation for pop member Function
Let us take a look at what the statement
count += (c == s.pop());
is doing.
The member function s.pop() is called. Since s is passed to the cnt_char() function "by value," a local copy of s is made inside the function and therefore the actual value of s is not being modified. When s.pop() is called inside cnt_char(), the first element of the local copy of s is being taken off the stack and the second element of local s becomes its first element.
The member function s.pop() returns the element that has been taken off the stack.
The returned element is compared to c. We wish to count the occurrences of c.
The returned value of (c == s.pop()) is either true or false. The TRUE, FALSE return values are interpreted as 1 or 0 by the compiler, where TRUE = 1 and FALSE = 0.
Depending on the return value of the == expression, count is either incremented by 1 or by 0.
This one statement could be translated into the following lines of code:
char* just_popped;
just_popped = s.pop();
if (c == just_popped)
count++;
The semantics of call-by-value require that a local copy of the argument type be created and initialized from the value of the expression passed as the actual argument. This requires a copy constructor.
General form and usage
A copy constructor has the form
type::type (const type&x)
and is used to perform copying of one type value into another when:
A type variable is initialized by a type value.
A type value is passed as an argument in a function.
A type value is returned from a function.
The fact that a copy has been created can be observed by noting that the value of name remains unchanged, even though the function modified the parameter variable. No copy constructor is used when you use a reference parameter.
String::String(const String& right)
{
len = right.length();
buffer = new char[len + 1];
for (int i = 0; i < len; i++)
buffer[i] = right[i];
buffer[len] = '\0';
}
Purpose:
The copy constructor will be invoked when a variable is declared using another variable as an argument.
In addition, copy constructors are used whenever an internal clone, or copy, of a value is needed. An example is creating a copy of an object to be passed to a value parameter.
When to Use System-Defined Copy Constructor
Unless the programmer provides one, the C++ compiler will automatically generate a copy constructor. This automatically generated function recursively invokes the copy constructor for each data field. This is termed a memberwise copy. In situations where a memberwise copy is appropriate (such as in the class Fraction), there is no need to write an explicit copy constructor or assignment operator. However, when classes use dynamically allocated memory (such as class String), this default behavior is usually not the desired action, and the functions should be defined.