C++/VB - Pass by value or reference

Asked By Jack
17-Jun-07 04:03 AM
void      SetWorldTransform( const D3DXMATRIX *pmxWorld );

is it better to use.... (DirectX stuff)

void       SetWorldTransform (const D3DXMATRIX& pmxWorld);

are they the same?
Thx
Jack
SetWorldTransform
(1)
MyClass
(1)
DirectX
(1)
Sldf73d1srgf5c0u8m5ed384jckoa1mj0h
(1)
VanDooren
(1)
PmxWorld
(1)
Dooren
(1)
Dougs
(1)
  Igor Tandetnik replied...
17-Jun-07 11:16 AM
They are. The generated assembly code will be identical.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
  Doug Harrison [MVP] replied...
17-Jun-07 02:48 PM
At the machine code level, they should be, but to the programmer, they are
different. I use references unless I have a reason to use pointers, and
those reasons include:

* The parameter is optional. Pointer parameters can be NULL, but references
must be bound to objects.

* I'm transferring ownership of a dynamically allocated object.

* I'm providing an interface for arrays.

* I'm overriding a virtual function. (Parameter lists must match exactly
for overriding to work.)

* I want to be consistent with existing practice.

If none of these apply, I use references. Most of the time, I use
references.

--
Doug Harrison
Visual C++ MVP
  Tom Serface replied...
17-Jun-07 08:41 PM
I'd bet they are the same code ultimately.  I have started using references
whenever possible since they are more useful in .NET so it is sort of a get
into the habit thing.

Tom
  MrAsm replied...
18-Jun-07 04:32 AM
On Sun, 17 Jun 2007 17:41:35 -0700, "Tom Serface"


With references we don't need to check that 'pMyPtrArgument != NULL',
so with references the code tends to be more elegant and robust, IMHO.

I do like and agree with Doug's "check-list" about reasons to
pointers.

MrAsm
  Bruno van Dooren replied...
18-Jun-07 04:43 AM
You forgot:

* my program is a C program, or it is a library and the headers might be
included in a C project.

--
Kind regards,
Bruno van Dooren  MVP - VC++
http://msmvps.com/blogs/vanDooren
bruno_nos_pam_van_dooren@hotmail.com
  Tom Serface replied...
18-Jun-07 10:07 AM
Hi Asm,

I can't argue (and wouldn't anyway) with Dougs list, or Bruno's addition to
it.  OP was asking about the code efficiency so I guessed OP was using C++.
There are certainly good reasons to use pointers in C++ in native and even
sometimes in managed code, but as you say, if possible it is more robust to
use references.  My guess is that's why they were invented :o)

Tom
  Doug Harrison [MVP] replied...
18-Jun-07 12:05 PM
Not much of a choice there, but OK. :)

--
Doug Harrison
Visual C++ MVP
  Ben Voigt [C++ MVP] replied...
18-Jun-07 11:21 PM
Even though the language standard says a NULL or invalid reference causes
same way as a NULL or wild pointer, and your functions should be written for
exception safety, in exactly the same way as you would with pointers.

After all, with pointers, you don't have to check either.  You can just
write the documentation to say "parameter y must be the address of ..., not
NULL".

So I disagree with the claim that references change the code in terms of
elegance, robustness, etc.  They really should be considered as a const
pointer (not pointer to const data).

In fact, I would say that references should only be used as either a local
alias, or as a reference to const data to avoid the memory copy overhead of
pass-by-value.  Non-const reference parameters are evil because the call
looks like pass-by-value but unexpectedly changes the source.  Of course,
the left side of operators like ++ or += are an exception to this, but
usually they would be class members anyway using the this pointer.  Changing
the right-hand-side in = or += is about as evil as you can get (and AFAIK
the only "expected" case of that is auto_ptr).
  MrAsm replied...
19-Jun-07 07:06 AM
On Mon, 18 Jun 2007 22:21:23 -0500, "Ben Voigt [C++ MVP]"



When I have pointers, I put at least an ASSERT( ptr != NULL ) (to be
evaluated in debug builds), and sometimes also a release build check
like ( if ptr == NULL ) return SOME_ERROR...;

I used to think that with references I was protected against this
problem.

void Test1( const MyClass * ptr );
void Test2( const MyClass & ref );

While I could mistakely pass a pointer whose value is NULL to Test1,
how could I pass a null reference to Test2?




I completely agree with your point about avoiding copy overhead with
reference to const data.



I don't agree with this.
IMHO, I find non-const references a good way to have IN/OUT
parameters...


MrAsm
  Igor Tandetnik replied...
19-Jun-07 08:12 AM
MyClass* ptr = 0;
Test2(*ptr);

--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
  David Lowndes replied...
19-Jun-07 09:15 AM
I suspect MrAsm's question was more along the lines of how can I do it
without trying too hard to fool the compiler :)


FWIW, the static code analyzer will detect this:


Dave
  MrAsm replied...
19-Jun-07 09:41 AM
Yes, you understand me, David.

MrAsm
  Ben Voigt [C++ MVP] replied...
19-Jun-07 12:00 PM
void Test2( const MyClass & ref );

void Test1( const MyClass * ptr ) { Test2(*ptr); }

The static code analyzer won't detect that, unless you have a fancy analyzer
that starts annotating each pointer with "can be NULL" and "can't be NULL",
but then references wouldn't gain you anything either.
  Doug Harrison [MVP] replied...
19-Jun-07 12:03 PM
On Mon, 18 Jun 2007 22:21:23 -0500, "Ben Voigt [C++ MVP]"


It's a fallacy to try to deal with wild pointers in terms of C++
exceptions. It would be OK (but strange) for a function that takes a
pointer to document it throws an exception when passed a NULL pointer.


That's well within the tradition of C. In C++, you can use references to
express that in code. It's also well within the tradition of C++,
considering that STL algorithms are defined on iterators, pointers are
iterators, and requirements include valid iterator ranges.


You have a point about robustness, in that it is typically possible to
create a reference bound to NULL. However, to do that requires that you
dereference a NULL pointer, and someone who can't get that right is just as
likely to pass wild pointers to pointer parameters, which can't be detected
in code, at least not with any reliability. On the other hand, someone who
can get this stuff right can use references correctly, and I don't think
consideration of the lowest common denominator should prohibit him from
using what is for him and like people a language feature that provides
increased elegance. (It's not going to provide much in the way of increased
robustness, because modulo the rare mistake, he was using pointers
correctly to begin with.)


I thought that the first six months I used C++, but then I realized I
shouldn't be forming expectations without having looked at the actual
functions and types involved. For example:

void f(int* p) { *p = 2; }

void g(int* x)
{
f(x);
}

Often, I'm interested in whether or not f(x) modifies *x, and I can't tell
that without looking at the code or consulting the documentation. Once I
realized that, I stopped thinking of f(&x) as providing a valuable
call-site clue. I've never regretted that shift in thinking.

As for when *not* to use references, don't use a const reference parameter
in a ctor and use it to initialize a const reference class member variable.
Since const references accept temporaries, it's far too easy to bind a
temporary to a reference such that the temporary doesn't outlive the
reference. It's OK to use non-const references in this context, with the
documentation caveat that the lifetime of the referent must outlive the
object's use of it. A good example of this is a lock class that takes a
reference to a mutex.

--
Doug Harrison
Visual C++ MVP
Create New Account
help
to create a copy constructor for this class and I don't get it. class myClass { int m_x; yourClass * m_yObj; myClass(myClass* mobj); }; myClass::myClass(myClass* mobj) { m_x = mobj-> m_x; m_yObj = ????? } How do I create a deep copy of the m_yObj to the translation. Please correct me so I may improve my English! VC Language Discussions MyClass (1) M_yObj (1) YourClass (1) OtherYObj (1) MrAsmRe (1) CloneYObj (1) MVP (1) MVPRe (1) Assuming the 'yourClass' is copyable using copy constructor: myClass::myClass( myClass * mobj ) { if ( mobj-> m_yObj ! = NULL ) { m_yObj = new yourClass( *mobj-> m_yObj ); } } MrAsm On Tue
CArray C++ / VB Ok here is sample of code: CArray <MyClass, MyClass> arr; MyClass * obj; obj = new MyClass(); obj-> some_field = some_value; arr.Add((*obj)); delete obj; - -- - Error 2664 Add cannot convert parameter 1 from class MyClass to class MyClass. Where is error?? or what I've missed? VC Language Discussions MyClass (1) CArray (1) Uli (1) Baseclasses (1) Constructor (1) Messaggio (1) Scritto (1) Vector (1) Try this: CArray< MyClass > arr; G BTW: this is unrelated to your original question, but your code seems a
C++ / VB I have a class in a dll that looks like: class _ _declspec(dllexport) MyClass { public: MyClass(void) ; ~MyClass(void) ; int x; };; in the implementation for the constructor, I have: MyClass::MyClass(void) { } When I use the dll in the client application to create a MyClass instance, the instance variable x is not initialized; I have a huge value like -842150451. Did I do something wrong? VC MFC Discussions MyClass (1) MOZART (1) MVP (1) HtmRe (1) MYCLASS_EXPORT (1) AFX_EXT_CLASS (1) DLL (1) XCDCDCDCD (1 mozart.co.uk For discussion / support see http: / / www.mozart.co.uk / mzusers / mailinglist.htm MyClass* myobj = new MyClass(); And what happens when you put a break point on it and
Can't read CString after serialization C++ / VB Hi, I have a CArray <MyClass, MyClass&> MyClassArray. MyClass contains various elements, int, double and a CString (ex. MyString). MyClass.cpp has the necessary Serialize statement. In my code, MyClassArray is generated as necessary and MyClassArray. At this point I get an error whenever I access the CString element in MyClass. I can access all other int or double elements in MyClass just fine. However, any access of the form - MyCArray.GetAt(i).MyString or - MyClass = MyCArray.GetAt(i); MyString1 = MyClass.MyString; gives a run time error in the MS file atlsimpstr.h. Here is the