From: marcomb on 27 Aug 2007 17:40 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 27 Aug 2007 17:58 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 27 Aug 2007 20:51 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 28 Aug 2007 02:52 "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 27 Aug 2007 17:58
"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 |