|
Hey Ben
This is a form of placement new. For example, the Add method makes space for the new object then calls SetAtIndex. Looks like the Wrapper class serves to provide the placement new, which allocates no space, and initialize the object by calling the ctor in the initialization list of the Wrapper constructor.
I think the basic idea behind placement new is efficiency - memory is allocated from a pool managed by the class, and new entries can be just added in and the count incremented. In this case, I guess things are additionally complicated by the templated type allocation, hence the need for the Wrapper.
There's probably a pattern here that some STL gurus would recognize - bet you could get a better explanation on comp.lang.cpp.moderated.
I'd like to understand this better myself - wonder if this kind of thing is standard practise in STL containers as well, or if there are other abtuse tricks afoot...
T
|
|
|
|
|
SetAtIndex creates new 'wrapped' object using placement new, but where's the destructor? I mean, if you call SetAtIndex and pass the index of already existing array element, the previous content should be deleted, right? Unfortunately, I don't have CSimpleArray sources - can't single-step through the code. The code posted here has a debug build index check and call to placement new.
Tomasz Sowinski -- http://www.shooltz.com.pl
|
|
|
|
|
Check out ATLBASE.H.
If you look at Add, RemoveAt, and RemoveAll you'll see where the space allocations are maintained, and dtors are explicitly called.
|
|
|
|
|
> Check out ATLBASE.H.
No such luck today I'm currently using a machine without any dev tools installed. Will have look tomorrow - SetAtIndex looks interesting.
Tomasz Sowinski -- http://www.shooltz.com.pl
|
|
|
|
|
Explicit dtor is missing from the SetAtIndex - every time SetAtIndex is called one object is 'wiped out' without invoking the dtor. Looks and feels like bug. CSimpleArray is a cheap kludge anyway - all data members are public, you can't pass const references as arguments to methods like Find, etc.
The code below demonstrates the problem with SetAtIndex:
#include <stdio.h>
#include <atlbase.h>
int ctorCalls = 0;
int dtorCalls = 0;
class Elem
{
public:
Elem() { value = 0; ctorCalls ++; Diag("def ctor"); }
Elem(const Elem& other)
{
value = other.value;
ctorCalls ++;
Diag("copy ctor");
}
~Elem() { dtorCalls ++; Diag("dtor"); }
void SetValue(int newValue) { value = newValue; }
private:
void Diag(const char *fxn)
{
printf("%s, this=%x, value=%d\n", fxn, this, value);
}
int value;
};
void test()
{
CSimpleArray<Elem> array;
Elem e;
e.SetValue(11);
array.Add(e);
e.SetValue(22);
array.Add(e);
e.SetValue(33);
array.Add(e);
e.SetValue(44);
array.SetAtIndex(1, e);
}
void main()
{
test();
printf("ctor calls: %d\ndtor calls: %d\n", ctorCalls, dtorCalls);
}
Tomasz Sowinski -- http://www.shooltz.com.pl
|
|
|
|
|
I dont think SetAtIndex is intended to be used outside the context of Add.
Since the primary purpose (documented anyway) of CSimpleArray is to provied a record container for CRowsetImpl, we could probably look at how its used there. I would imagine it's treated like CSimpleValArray, which pares down the interface to the working norm of Add(), operator[](), and Remove().
Found this in the MSDN as well - but haven't looked at it:
The CMSPArray template implements a smart array that will grow on demand. It is designed to hold small arrays with simple data types. It doesn't have a critical section. Its only dependencies are realloc and memmove. It is used internally to keep lists of object pointers. It is similar to ATL 2.1's CSimpleArray implementation, but it is more efficient for initial allocations.
This template is defined in MSPutils.h.
|
|
|
|
|
Thanks Tim, it make a little more sence now, but I'm not usre is see that its more efficient. Maybe its a way to allow object's with no copy operator to be copied?
-Ben
"Its funny when you stop doing things not because they’re wrong, but because you might get caught." - Unknown
|
|
|
|
|
> Maybe its a way to allow object's with no copy operator to be
> copied?
You mean the assignment operator, right? Yes, this method makes it possible. You're creating new objects at address CSimpleArray already knows. The class you're storing in CSimpleArray only needs public copy constructor.
Note that SetAtIndex has a bug: it doesn't explicitly invoke destructor for 'previous' object - the one that occupied nth index before calling SetAtIndex. For more details check my reply to Tim in this thread.
Tomasz Sowinski -- http://www.shooltz.com.pl
|
|
|
|
|
I took a look at the CMSPArray in MSPutils.h (platform SDK includes). Looks like it could have been cloned from CSimpleArray, or vice versa, save for a few calls. The most notable difference is that it doesn't bother supporting non POD types - no ctors or dtors are called.
In this class, the line in SetAtIndex you highlighted in your original post is simply
m_aT[nIndex] = t;
So, the whole trick seems to boil down to basing a simple container on realloc and memmove while supporting non POD types. If you were to start from CMSPArray and add support for non POD types, you might wind up with CSimpleArray - but that Wrapper class sure is a brain twist.
As for effeciency, I think it probably depends on the context, types stored, etc. Maybe as a container for hundreds of recordsets CSimpleArray is a good choice.
later
Just occurred to me that another difference from this and a standard container is the lack of the need for a defined operator < for its types - again, makes sense for a simple array of things like db records.
|
|
|
|
|
Hi
I need to know if anyone have good VC++ Source for a Cataloguer like "Advanced Disk Catalog" or any good reference site ?
TIA
BLaZe
|
|
|
|
|
to compare 2 strings one uses strcmp, but what about integers? is there a strcmp alternative for int/float?
check out the code see what i mean
void binSort(FILE * pt, int struSize, int n)
{
float i, j, minPos;
struct Planet iRec, jRec, temp;
for(i = 0; i < (n-1); i++)
{
fseek(pt, 0L, SEEK_SET);
fseek(pt, (i*struSize), SEEK_CUR);
fread(&iRec, struSize, 1, pt);
for(j = (i+1); j < n; j++)
{
fseek(pt, 0L, SEEK_SET);
fseek(pt, (j*struSize), SEEK_CUR);
fread(&jRec, struSize, 1, pt);
if(strcmp(jRec.diameter, iRec.diameter) < 0)
{
temp = iRec;
iRec = jRec;
jRec = temp;
fseek(pt, 0L, SEEK_SET);
fseek(pt, (i*struSize), SEEK_CUR);
/*swap records*/
/*fwrite(&iRec, struSize, 1, pt);*/
printf("iRec = %fn", iRec);
fwrite(&iRec, struSize, 1, pt);
fseek(pt, 0L, SEEK_SET);
fseek(pt, (j*struSize), SEEK_CUR);
fwrite(&jRec, struSize, 1, pt);
}
} /*end j*/
} /*end i*/
}
its all good until 'if(strcmp(jRec.diameter, iRec.diameter) < 0)'. since jRec/iRec.diameter are declared as floats i get mismatch errors. im working with structures, files, etc, so i wanna know if there are any strcmp alternative or do i have to code a seperate function?
|
|
|
|
|
If the "diameter" member is just a float, use the normal < operator:
if ( jRec.diameter < iRec.diameter )
--Mike--
http://home.inreach.com/mdunn/
#include "buffy_sig"
|
|
|
|
|
1.
What is the best progress for loading images and displaying them on a DC? Is there a single function covering this?
I know from DirectX that there is a standardfunction for loading .BMP's there, but the GDI/DC-world is new to me..
2.
I try to do DestroyWindow() to quit my DialogueBox, however, I only get "Debug Assertion Failure".. what's the correct way to shut down your own window?
On forehand thanx,
Thomas
|
|
|
|
|
(addressing question 2) Where is the assert? What test is failing?
If your dialog is modal, you use EndDialog(). DestroyWindow() is used only for modeless dialogs.
--Mike--
http://home.inreach.com/mdunn/
#include "buffy_sig"
|
|
|
|
|
Yes, EndDialog(int) did the trick, thanks a lot!
You wouldn't know how to load and display images from Win GDI as well?
Thomas
|
|
|
|
|
GDI+ knows how to load images from disk, in GDI you can use ::LoadImage to load a .bmp, but no other format is supported. You can try a library like paintlib if you want to load jpg, etc. You need to load the image in and select it into a DC. Then you can manipulate it or copy to a ClientDC/PaintDC if you want to see it.
Christian
#include "std_disclaimer.h"
People who love sausage and respect the law should never watch either one being made.
|
|
|
|
|
Yes, LoadImage is present for DirectX too, and only .bmp-files also for that.. great, I couldn't find it anywhere in my MSDN lib because I thought it had a different name.
I will try out the paintlib; it'd be nice to be able to load jpg's too..
Thanks again (to both of you)!
Thomas
|
|
|
|
|
I wondering what code is that ti be added to a dialog based app if I want serialazing?
BETA
|
|
|
|
|
I wondering what code is that ti be added to a dialog based app if I want serialazing?
BETA
|
|
|
|
|
I'm working on a project that has to extract data from an INI file using GetPrivateProfileString. Under Windows 2000, my code works fine, but under Win9x and WinME, it fails.
The INI file in question is formatted like so:
[ SectionName ]
KeyName = SomeValue\t\t; comment
Notice that there are spaces in the "[ SectionName ]", as well as before and after the "=" sign in the key value assigments.
I'm using this code to read the file:
GetPrivateProfileString(" Section Name ", "KeyName", "", 255, "C:\Path\MyFile.ini");
I've tried all combinations of leading and trailing spaces for the section and key names in the GetPrivateProfileString call, but it still refuses to work in Win9x. I can't change the file tro be "compatible" because I'm not the one that generated the file, and besides, it might screw up the original program if I did so.
Anybody got any hints or suggestions?
|
|
|
|
|
I *was* going to point out that .ini files are six years obsolete, but apparently you're stuck with them. I'm surprised at the order of your problem, I'd have thought if anything the legacy code would be broken later ( i.e. Win2K ) rather than a problem where only Win2K works. Is there any reason why you can't just open the file and parse it yourself ?
Christian
#include "std_disclaimer.h"
People who love sausage and respect the law should never watch either one being made.
|
|
|
|
|
Well, I'm not really a believer of Microslop's mantra that all program settings belong in the registry, so I only use it when it's required. But beyond that little personal item....
I'm gonna try just removing the offending white spaces from the file, and writing it back to the disk. Then, it *should* work fine on any version of Windows. How it affects the original program that uses this file has not yet been determined.
This is admittedly the most bizarre thing I've seen in a while (if you don't count .NET).
|
|
|
|
|
I scrubbed the files and a) the original program that uses them still works, and b) now mine does too.
The requirement to do so is freaky though.
|
|
|
|
|
Hi !
How can I get a controls HWND ?
|
|
|
|
|
For example the ID of the dialog control is IDC_BUTTON2.
CWnd *pWnd = GetDlgItem(IDC_BUTTON2);
if (pWnd)
{
HWND hwnd = pWnd->m_hWnd;
// hwnd is your handle to the control
}
I hope I could help you...
Gregor Mitsch
E-Mail: abacus-@gmx.de
|
|
|
|
|