Journal Articles

CVu Journal Vol 12, #4 - Jul 2000
Browse in : All > Journals > CVu > 124 (22)

Note: when you create a new publication type, the articles module will automatically use the templates user-display-[publicationtype].xt and user-summary-[publicationtype].xt. If those templates do not exist when you try to preview or display a new article, you'll get this warning :-) Please place your own templates in themes/yourtheme/modules/articles . The templates will get the extension .xt there.

Title: Questions and Answers

Author: Administrator

Date: 06 July 2000 13:15:38 +01:00 or Thu, 06 July 2000 13:15:38 +01:00

Summary: 

Body: 

I know that most if not all the questions that get posed in this column have been answered either privately or elsewhere long before you get your chance. However, contributors gain many benefits from their efforts. So do readers and those posing questions.

Getting a question into a comprehensible form often results in the answer being 'obvious'. Formulating a written answer to a question often leads to unanticipated insights. I know that many readers have severe demands on their time, but a few minutes (OK, half an hour) developing a response while waiting for a meeting, stuck in a traffic jam etc. will be an investment.

On the other side, if you find yourself checking reference books or asking your local Guru for help, you have a question worth presenting here. You could even provide both question and your tentative answer. You might then be surprised by how often your local expert knows less than you thought.

Please note that questions remain open. In other words, if you have something to add to an earlier answer, or even realise that you can answer an earlier unanswered question, please put fingers to keyboard, or get talking to your voice recognition software.

Some Answers

Question 3 (C Vu 12.3)

Can someone please explain in detail what the -> (arrow symbol) does in C++.

Answer From the Harpist

Let me start by looking back at its origin in C. At that stage it was completely unnecessary from the language aspect. There was no need for it. The dot operator could have met all your needs. Applying the latter to an object would result in the following member being selected, applying it to a pointer to object would still result in the following member being selected. The compiler would know if it were applied to an object or to a pointer. However, programmers take time to become comfortable with such built-in operator overloading (even though it is not significantly different from the way the arithmetic operators vary their implementation according to context)

Let me give an example:

struct X {
  int a, b;
} x;
int main(){
  struct X * x_ptr = &x;
  x.a = 3;    // fine
  (*x_ptr).b = 4;  // fine
  *x_ptr.b = 5;  // error, wrong operator precedence
  x_ptr.a = 6;  // error x_ptr is not an X
  return 0;
}

Effectively, the arrow operator was introduced into C as a shorthand way of writing (*x_ptr).b as x_ptr-> and eliminate errors such as the first one above which may not always be diagnosable (think of having a pointer as a member). However, apart from human discomfort, there was no reason why the second error should not have been legitimised by simply defining that applying the dot operator to a pointer resulted in dereferencing followed by selection.

The decision made by the designer of C (Dennis Ritchie) proved to be of tremendous value, not in C but in its offspring, C++.

C does not provide any mechanism for users to define overloads for operators (perhaps it should be considered, in a limited fashion, for a future release) but C++ does. Without the existence of the arrow operator C++ would have been much poorer. Had C taken the alternative route indicated above, legacy code would have locked C++ into raw, C-style, pointers. However, given this almost useless C-operator C++ has been able to build a powerful superstructure.

When your compiler comes across and arrow in your code it checks to see if the left-hand operand is a pointer or an object (exactly the way that C could have checked the dot operator). If it is a pointer, it first dereferences it (gets hold of the thing pointed to) and then selects the member of that object designated by the right-hand operand. In other words, it treats it exactly the way C would. The fun comes when the left-hand operand is an object. In this case it has to search the type of that object for a declaration of operator->, and apply that to the left-hand object. Now it has to check what results, if it now has a pointer it passes that and the right-hand operand to the built-in arrow operator (the C-style version).

However, if the return is another object (value or reference) it repeats the procedure of finding a user-defined operator->. Fortunately, this kind of recursive application of user-defined arrow is rare.

The advantage of all this complexity is that programmers can develop smart pointers. These are operators that have pointer like behaviour plus something extra. A good (bad from some perspectives) example of such a type is the C++ Standard Library's auto_ptr<>. However, smart pointers do not have to be templates, though if you are going to go through all the pain of developing one you might as well maximise the payback.

More Questions

Question 1 from Robert Lytton

My opinions on using const and when to use it are still very fluid but here are my thoughts so far.

I have had to use a library in the past that have given function prototypes in the style int AmmendString( char* , char*, int); The library was documented but it would have be nice to have some documentation in the prototype itself, int AmmendString(char* line, char* word, int count); It would also have liked a clue to whether the function alters the data pointed to? By adding const, int AmmendString(char* line, const char* word, int count); it allows me to assume that the data pointed to by word will not be altered [pointer to const string] while that of line 'may' be altered!

What if the function was long and involved, are the parameters valid throughout the function? If I needed to add some functionality I would have to check carefully that they were not altered, - count; and if I altered them I may cause problems latter. By making the parameters const, int AmmendString( char* const line, const char* const word, const int count); we can rely the parameters not changing [line is a const pointer to a string, word a const pointer to a const string and count is const too], unless someone has chosen to cast the const away.

Could the use of const help a compiler optimise code?

In C++ the return type is made const when it is an rvalue, const Type operator+( const Type& lhs, const Type& rhs ); for example:

Type a, b, c; a+b = c;

If a+b returns a const, an error will be generated However it seems that when returning a built in type the const is not generally used...

Question 2 from Aaron Ridout

Am I being stupid, or does this:

std::cout << "Some Text " << std::ios::hex 
           << x << std::endl ;

take longer to execute than this:

printf( buffer, "%s %x\n", "Some Text ", x ) ;

I am not going to answer this now, but there are several issues that readers might like to consider. The first is the impact that C++'s default support for mixing C and C++ usage of the standard streams. The second is the degree to which problems are caused by the strategy of current implementations of the C++ Standard Library. FG

Question 3 from Aaron Ridout

I use the STL containers: list, vector, map etc. quite a lot, and often in my designs where there are two or more threads, one ends up with a container, such as std::list<>, to balance out communications between the two threads... Now what I would like to do is add one of these wonderfully useful sentry classes to the std::list so that it was endowed with thread safety.

How do I do this?

Question 4 from anon

In Java I am used to providing exception specifications and find them essential. What is the problem with them in C++?

Notes: 

More fields may be available via dynamicdata ..