Link to home
Start Free TrialLog in
Avatar of cwilliso
cwilliso

asked on

2 C++ Pointer/Reference Questions

I am a little bit rusty on my C++, and have a couple of questions:

1.) In the following program, how can I pass a pointer to the variable tmpString
     instead of passing a reference.  Is it the same thing? Why? (String is a class)
    Do I have to use a new() function to get a pointer to a class?

..
..
String tmpString;

tmpString = "hello";
my_function(tmpString);
...

void my_function(String &tmpString)
{
   if (tmpString ....) {
   ...
   ...
   }
}

What I want to do (but won't compile....)
..
..
String tmpString;

tmpString = "hello";
my_function(&tmpString);
...

void my_function(String *tmpString)
{
   if (*tmpString ....) {
   ...
   ...
   }
}


2.)   In the following program, how can I create an "alias" to the long pointer description
       show, Form6->.......  So I can simply reference the strings by saying like str1 = alias[x];

....
str1 = Form6->ListBox1->Items->Strings[x];

want:
str1 = alias[x];


ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of alamo
alamo

Your first example should be just fine; what error does the compilation give? (If you use member functions on the String the syntax of those will change, though, perhaps you should give the full details of "if (*tmpString ....) { ").

On the second question: seems like #define would work just fine.
Question 1 is actually several questions, and I'm going to answer them in a different order:

>>    Do I have to use a new() function to get a pointer to a class?

No.  You can generate a pointer to an object (not a class, an object) using the & operator, like

int I;
int *IPtr = &I;

This creates a local integer varaible called I and then creates a pointer to it using the & operator.  (Pointer is then stored in an integer pointer variable called IPtr.)    When you use the new operator you get a pointer to a new object, but as you can see that is not the only way to get a pointer to an object.  Note however, that the delete operator should only be called on a pointer to a dynamically allocated object.  It would be a mistake to call delete on the IPtr in the above example.

>> how can I pass a pointer to the variable tmpString  instead of passing a reference.  

Declare the function as taking a pointer by changing the & to a * like

   void my_function(String *tmpString)
   {
      if (tmpString-> ....) {
      ...
      ...
      }
   }

>> Is it the same thing? Why?

Yes and no.  First of all a reference is implimented using a pointer, so the two will result in the same object code.  That is the two versions will produce the same CPU instructions.  The only difference is syntax.  But this is not a small difference.  But first of all, one important point.  When a parameter is passed by reference or by a pointer the procedure can change caller's value of the parameter.  This can be a useful feature at times.  But it can be a problem if the caller doesn't want (doesn't expect) the value to change.  When a parameter is passed by value, the function cannot chnage the caller's value, so there is no danger here.  Now, why is this important?  It is important because passing by reference and passing by value look the same.  In the following code

   String tmpString;
   tmpString = "hello";
   my_function(tmpString);

myfunction() could take the string by value or by reference.  There is no way to tell unless you look at the code for my_function().  So there is no way to tell if tmpString will be altered without looking at my_function().  However, if the function takes a pointer instead it will look like

   my_function(&tmpString);

and it comes quit clear that the function can alter the string.   This difference is important enough that some people will allways pass with pointers instead of references.  (But I prefere references.)

continues.
One more point about the difference between pointers and references.  You can have a NULL pointer, but there is no NULL reference. Thus if you write a function that takes a parameter by pointers, you need to make sure that it can handle a NULL pointer or that it is documented that it cannot take a NULL pointer.  This is not an issue if it takes a reference.

>>   In the following program, how can I create an "alias" to the long pointer
>> description   show, Form6->.......  So I can simply reference the strings
>> by saying like str1 = alias[x];

If strings is an array of "String" objects, then you can use

String &Str1 = Form6->ListBox1->Items->Strings[x];

note how this is similar to the pointer form

String *Str2 = &(Form6->ListBox1->Items->Strings[x]);

One difference is that pointers objects can be changed to point to new objects, but references cannot  so for example.

String &Str1 = Form6->ListBox1->Items->Strings[x];   // Okay
String *Str2 = &(Form6->ListBox1->Items->Strings[x]);  // Okay
Str2 = &(Form6->ListBox1->Items->Strings[x+1]);  // Okay.   Points can be changed.
Str1 = Form6->ListBox1->Items->Strings[x_10];   // Compiler error.  Reference can't be changed.

continues.

Opps the last continues was a mistake.  I'm shutting up now, unless you have questions.
Seems to me that the most basic question - Why won't this compile? - was never answered.

I had interpreted the second question slightly differently - I assumed cwilliso wanted a shorthand form you could use multiple times varying the [x], which you can do with a #define but not with a pointer or reference.
He doesn't ask "why won't this compile?" At least not that I can see.   I don't think its an issue, because he has only shown one or two code snippets.  (They should compile fine however.)

I would not use #define for that purpose.  it is okay for controlling conditional compilation of features, like large libraries and debugging code.  Using it in this sort of case is unnecessary at best and risky at worst.  Just say no to #'s.
I agree #define is at times dangerous, but arguably no more so than the use of references. And as I read original question,  cwilliso wanted a shorthand (probably to make the code easier to read and understand). #define is often the best way to do this, and in this case I think the only way.
Not the only way and probably a less good way--baring a really good optimizer.  (Which frankly doesn't exist yet.)

Code like

Form6->ListBox1->Items->Strings[x];

will result in 4  pointer dereferences each time it appears and is quit inefficient.  if you use a #define for this then you will have the 4 derefences each time you use the define.  On the other hand, if you use a reference like

String *StrRef = Form6->ListBox1->Items->Strings[x];

You will have 3 dereferences and here and only one derefences each time you use StrRef.  Thus if you use StrRef one time it is about equal to the #define in processor time.  If you use StrRef more than one time it saves time (and space).  

The other benefits are that the reference obeys C++'s rules for scope and type safety.  Not so with the #define.  This makes the #define particularlly dangerious.  
Of course the define (in this case) obeys the rules for scope and type safety, since it is expanded at compile time and the resulting code must obey those rules. Scope/type safety is one of the arguments against #define, but not as #define is used here.

My major point, though was that you can't do:

#define alias Form6->ListBox1->Items->Strings
str1 = alias[x];
str2 = alias[x+1];

using a pointer or reference, and that's what I thought the question was about, and the case in which #define is arguably useful.  If efficiency more important than readability, then a pointer or reference is better but requires you to change how you access the final string. It all depends on your priority in a given piece of code.
>> Of course the define (in this case) obeys the rules for scope and type safety, since it is expanded at compile time and the resulting code must obey those rules.

No it doesn't.  A #define created in one procedure can be used in another.  That is a scope violation and can lead to accidental problems.  A #define created to work with one type can be used with another, this can lead to problems again.

>>My major point, though was that you can't do:
>>#define alias Form6->ListBox1->Items->Strings
>>     str1 = alias[x];
>>     str2 = alias[x+1];

Agreed, but this type of access is ussually (admitidlly not always) in a loop, so you can create a reference that is local to a loop.