From: marcomb on
I have read in a book about CArray, CList and CMap.
The book says that for example Carray class everytime we add an object,
MAKES a copy of the object we need to store, so we need probably to implement
a copy constructor.
But it also says as it's true, that we quite always use Reference as
Argument Type, to evitate COPIES...passing by reference,so address and not by
value.
I'm quite confusing...the copies is made or not in our CArray object?
If the copy wasn't made we would have a CArray class object that would
contain addresses or pointers, equals to CTypedPtrArray....
so for example:

CArray<CPoint, CPoint&> PointArray;

CPoint aPoint = new CPoint(...paramlist...);

PointArray.Add(aPoint);

so we pass aPoint by reference, but still we create a copy of it in
PointArray or what else?Pointarray manage only address of aPoint?
and if my declarations was:

CArray<CPoint, CPoint> PointArray;

CPoint aPoint = new CPoint(...paramlist...);

PointArray.Add(aPoint);

and also...

CArray<CPoint, CPoint*> PointArray;

CPoint aPoint = new CPoint(...paramlist...);

PointArray.Add(aPoint);

what's the difference from

CTypePtrArray<CObList,CPoint*> PointArray;

CPoint aPoint = new CPoint(...paramlist...);

PointArray.Add(aPoint);

Thanks a lot for all responses.


From: Jonathan Wood on
marcomb,

>I have read in a book about CArray, CList and CMap.
> The book says that for example Carray class everytime we add an object,
> MAKES a copy of the object we need to store, so we need probably to
> implement
> a copy constructor.
> But it also says as it's true, that we quite always use Reference as
> Argument Type, to evitate COPIES...passing by reference,so address and not
> by
> value.

Correct.

> I'm quite confusing...the copies is made or not in our CArray object?

Yes. The object is passed by reference, which the method in question then
copies.

This is because it is more efficient to pass a reference of most objects
than to try and pass by value, which doesn't even make sense with many
object types. But this does not say anything about what is stored by a
method that you pass the reference to.

> If the copy wasn't made we would have a CArray class object that would
> contain addresses or pointers, equals to CTypedPtrArray....
> so for example:

A copy is made.

--
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com

From: David Wilkinson on
marcomb wrote:
> I have read in a book about CArray, CList and CMap.
> The book says that for example Carray class everytime we add an object,
> MAKES a copy of the object we need to store, so we need probably to implement
> a copy constructor.
> But it also says as it's true, that we quite always use Reference as
> Argument Type, to evitate COPIES...passing by reference,so address and not by
> value.
> I'm quite confusing...the copies is made or not in our CArray object?
> If the copy wasn't made we would have a CArray class object that would
> contain addresses or pointers, equals to CTypedPtrArray....
> so for example:
>
> CArray<CPoint, CPoint&> PointArray;
>
> CPoint aPoint = new CPoint(...paramlist...);
>
> PointArray.Add(aPoint);
>
> so we pass aPoint by reference, but still we create a copy of it in
> PointArray or what else?Pointarray manage only address of aPoint?
> and if my declarations was:
>
> CArray<CPoint, CPoint> PointArray;
>
> CPoint aPoint = new CPoint(...paramlist...);
>
> PointArray.Add(aPoint);
>
> and also...
>
> CArray<CPoint, CPoint*> PointArray;
>
> CPoint aPoint = new CPoint(...paramlist...);
>
> PointArray.Add(aPoint);
>
> what's the difference from
>
> CTypePtrArray<CObList,CPoint*> PointArray;
>
> CPoint aPoint = new CPoint(...paramlist...);
>
> PointArray.Add(aPoint);

marcomb:

Part of the reason you are confused is that the double template argument
in the MFC collection classes is very confusing, and (IMHO) unnecessary.
The C++ stadard library classes like std::vector have no such double
argument, In fact, in recent versions of MFC the second argument is
defaulted

template<class TYPE, class ARG_TYPE = const TYPE&> class CArray:
public CObject
{
};

But all of your examples are actually wrong (and will not compile)
because you are mixing objects, references and pointers in invalid ways.

Two correct ways are

// array holds objects
CArray<CPoint, CPoint&> PointArray;
CPoint aPoint(...paramlist...);
PointArray.Add(aPoint);

// array holds pointers
CArray<CPoint*, CPoint*> PointArray;
CPoint* pPoint = new CPoint(...paramlist...);
PointArray.Add(pPoint);

HTH,

--
David Wilkinson
Visual C++ MVP
From: Giovanni Dicanio on

"marcomb" <marcomb(a)discussions.microsoft.com> ha scritto nel messaggio
news:9772B215-BED7-4E85-B55B-8BC712C9D180(a)microsoft.com...
>I have read in a book about CArray, CList and CMap.
> The book says that for example Carray class everytime we add an object,
> MAKES a copy of the object we need to store, so we need probably to
> implement
> a copy constructor.
> But it also says as it's true, that we quite always use Reference as
> Argument Type, to evitate COPIES...passing by reference,so address and not
> by
> value.
> I'm quite confusing...the copies is made or not in our CArray object?

Hi marcomb,

it is more a C++ language issue than a MFC one.
You should have clear that, when you have code like:

void Func( int x )
{
x++;
}

a *copy* of x is passed to Func; inside Func, the copy is modified, so there
is no modification on the original parameter.

e.g.

int a = 3;
Func( a );
// 'a' still == 3

In fact, if you want to swap two variables, you should use *pointers* or
*references* to pass the variable to the swapping function, e.g.:

void Swap( int * pa, int * pb )
{
int temp;
temp = *pa;
*pa = *pb;
*pb = temp;
}

and use like so:

int a = 3;
int b = 10;
Swap( &a, &b );
// Now: a = 10, b = 3

Of course, in C++ you can also use *references* instead of pointers, e.g.:

void Swap( int & a, int & b )
{
int temp;
temp = a;
a = b;
b = temp;
}

and use like so:

int a = 3;
int b = 10;
Swap( a, b );
// Now: a = 10, b = 3

The sample #1 shows passing "by value" semantics; the samples #2 and #3 show
passing "by reference" semantics (even if #2 uses C++ pointers, and #3 uses
C++ references).

If your parameter is an instance of a C++ class, and you pass it *by value*,
then the copy constructor is invoked by the compiler, e.g.:

class MyClass
{
public:
MyClass() : x(0) {}

// Copy ctor
MyClass( const MyClass & src )
: x( src.x )
{
cout << "MyClass copy ctor invoked." << endl;
}

int x;
};

void TestValue( MyClass c )
{
c.x = 1000;
}

void TestReference( MyClass & c )
{
c.x = 1000;
}

If you call TestValue, you will read the message "MyClass copy ctor
invoked", in fact the copy ctor is invoked because you are passing by value.
Moreover, the x data member of the parameter will not be changed (because a
local copy of the instance is done inside the TestValue body).

Instead, if you call TestReference, you will not read the copy ctor message,
because *no* copy ctor is invoked. And the x data member of the passed
instance will be set to 1000, beacuse a *reference* to the class instance is
passed to the function.

When you pass "big objects" to functions or methods, you should prefer
passing references or pointers to these big objects, so you can avoid
performance-costly copy ctors (basically, when you pass by reference, you
just pass the "address" of the class instance, not a copy of it).
Moreover, if you want to *modifiy* the parameter, then you must pass by
reference or pointer, because it is the only way to make the modification
(the function must know the address of the class instance, to modify it).

You might consider this C++ FAQ-lite useful:

http://www.parashift.com/c++-faq-lite/value-vs-ref-semantics.html#faq-31.1

Giovanni


From: David Webber on

"marcomb" <marcomb(a)discussions.microsoft.com> wrote in message
news:9772B215-BED7-4E85-B55B-8BC712C9D180(a)microsoft.com...

> CArray<CPoint, CPoint&> PointArray;

This hold a collection of CPoint's. Not references to CPoint's or
pointers to CPoint's.

> PointArray.Add(aPoint);

This makes a copy in the array.

> so we pass aPoint by reference, but still we create a copy of it in
> PointArray

Yes.

> CArray<CPoint, CPoint> PointArray;

I don't think there is any need to do that. The second template argument
is to do with how things are referenced; the first argument is the thing
stord.


> CPoint aPoint = new CPoint(...paramlist...);
>...

That should not compile. (new returns a pointer).

> CArray<CPoint, CPoint*> PointArray;

I would guess that will probably not work. use

CArray< CPoint, CPoint &>


> CPoint aPoint = new CPoint(...paramlist...);

Again new returns a pointer.

PointArray.Add(aPoint);
>
> what's the difference from
>
> CTypePtrArray<CObList,CPoint*> PointArray;

Do you mean CTypedPtrArray ? I am not sure it is legal with a CObList,
but CTypePtrArray is used typically with an array of pointers.

> CPoint aPoint = new CPoint(...paramlist...);

Again new returns a pointer.

In pracice I'd use std::vector instead of CArray these days. You can store
an array of "things" (which need a copy constructor when you add them to the
array) or an array of "pointers to things". It's your choice. In either
case be careful about scope, and to delete things created with new at the
appropriate point in order to avoid memory leaks.

Dave
--
David Webber
Author of 'Mozart the Music Processor'
http://www.mozart.co.uk
For discussion/support see
http://www.mozart.co.uk/mzusers/mailinglist.htm