Right. :)
Printable View
The hackish way to do this with MFC is to copy the CList to a temp CArray, sort the CArray using std::sort, and then rebuild the CList from the sorted CArray.
That was the usual solution I have given here in the past. Produces the least bugs, and efficiency isn't too bad.
Regards,
Paul McKenzie
Code:qsort(arr.GetData(), size, sizeof(CString*), CompareStrings);
If you used undefined behaviour for cStringArray, I should be able to use undefined behaviour for vector. Vector would win in this case.Quote:
Originally Posted by Philip Nicoletti
letting undefined behaviour slide like that will never be portable. microsoft's code sometimes is not so great at times, but I would never use such disregard by using non-pod as pod. This will lead to even more undefined behaviour... like trying to call a variadic function with non-pod arguments and expect defined results.
if you want to time something fairly, I will be more than happy to compare results
Here is the stl_sort fixed to improve speed
MFC wayCode:// stl_sort.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "array.h"
bool Comp( const CString& first, const CString& second)
{
return first.Compare( second );
}
int _tmain(int argc, _TCHAR* argv[])
{
ShowWindow(::GetConsoleWindow(), SW_HIDE);
const size_t size = GetArraySize();
LARGE_INTEGER begin, end, freq;
::QueryPerformanceFrequency(&freq);
::QueryPerformanceCounter(&begin);
std::vector<CString> v;
v.assign( &g_strings[0], &g_strings[ size ] );
::QueryPerformanceCounter(&end);
double fill = ((double)end.QuadPart - begin.QuadPart) * 1000.0 / freq.QuadPart;
::QueryPerformanceCounter(&begin);
std::sort(v.begin(), v.end(), Comp);
::QueryPerformanceCounter(&end);
double sort = ((double)end.QuadPart - begin.QuadPart) * 1000.0 / freq.QuadPart;
CString strResult;
strResult.Format(_T("Array size: %u")
_T("\nFill time: %lf ms.")
_T("\nSort time: %lf ms.\n"),
size, fill, sort);
::MessageBox(NULL, strResult, _T("STL WAY"), MB_OK);
return 0;
}
Array size: 29979
Fill time: 7.638157 ms
Sort time: 10.190586 ms.
Stl way
Array size: 29979
Fill time: 6.434275 ms
Sort time: 15.723842 ms.
mfc way total = 17.828743
stl way total = 22.158117
stl is a tad bit slower, but portability and standard comes to mind. I am all for speed, but not when it breaks standard rules. I hate tracking bugs down and creating them on purpose to begin with isn't the way I want to start off creating a project.
You're passing a function pointer into sort(), there. While it's possible the compiler might be able to inline that, in general it's easier to inline functors. I'd be curious to know if it does any better if you define it as:
Code:struct Comp
{
bool operator()( const CString& first, const CString& second) const
{
return first.Compare( second );
}
};
....
std::sort(v.begin(), v.end(), Comp());
The result was the same in this case.
You could also have combined construction and assignment, though I doubt that would have made any noticeable difference.
Code:std::vector<CString> v( &g_strings[0], &g_strings[ size ] );
It's amazing how so many people keep failing to answer the question.
The original poster asked which containers were faster, and which were better. He didn't ask for people to go off on a ideological trip about standards.
I'll only address the speed question. In my tests, STL containers are not always particularly fast. In many cases, the MFC containers are faster, sometimes dramatically so. If speed is your concern (and it's sometimes an absolutely fundamental issue), I would tend to favour the MFC containers, but it's better to evaluate on a case-by-case basis. My advice: do a comparative test with both with the kind of data your app will use.
A hopelessly slow application in 100% standard C++ is no use to anybody.
Can you post your tests ?? It has been shown on Codeguru and other locations
the std::vector is as fast or faster than CArray. (I hope you were not testing
Debug version or with iterator checking).
Isn't discussion of "better" include discussion of standards?
Let's see your tests against optimized code, with the proper preprocessor flags used in creating the program (_SECURE_SCL=0 is the one that people often missed if you use Visual Studio).Quote:
I'll only address the speed question. In my tests, STL containers are not always particularly fast. In many cases, the MFC containers are faster, sometimes dramatically so.
Show your tests. Compiler, version, whether it is optimized properly, etc.Quote:
A hopelessly slow application in 100% standard C++ is no use to anybody.
Regards,
Paul McKenzie
Paul, have you ever tried the "sorting project" posted here with and without _SECURE_SCL=0 or we are just talking using "holy scripts"?
Regards,
Ovidiu
The _SECURE_SCL=0 turns off iterator checking in release mode. With iterator checking on, the code will show degradation. It seems your original project did not have this set in release mode. Rerun your tests, but set this flag.
The issue is that Visual Studio doesn't have this set to 0 when building a release version, thereby the STL applications were slower than they should be if you were not aware of this flag. This has been reported to MS as to the flaw, and some haven't had too many nice words to say to the VS engineers about it.
Secondly, I think I mentioned that STL is not just containers -- you have the algorithm functions. MFC doesn't have these functions, so the advice "never to use STL in an MFC application" needs to be clarified.
Regards,
Paul McKenzie
I knew that.
Ok, seems to be logical and good to add "no additional run-time checking, means more speed" in Programmer's Holy Book.
However, until seeing somethig is really real, I'm Thomas The Unbeliever Programmer so I said: "Let's try it!".
I was expecting a significant speed increasing by disabling run-time iterators checking (setting _SECURE_SCL=0), but... surprise: the result was quite the same.
Or course, would be stupid to generalize and take that as a generally true statement.
In other non-trivial cases, the result may be as "canonically" expected.
Maybe I was wrong, then you can try it. That program is not tabu and doesn't bite. :).
I said:
Is it absolutelly necessary to show "if it's not absolutelly necessary" phrase by using big bright letters and having Las Vegas effects? :D
Well, I developed MFC applications for years and, generally, there were rare cases of "absolutelly necessary".
One beside note.
Run-time ckecking is not evil. In many cases, a little bit smaller speed performance is preferable to other nasty problems.
As an example, once I found something like this:
This is just a trivial example. May be others, having more insidious sources of painful run-time headaches.Code:v.erase(iter);
//...
--iter;
We believe or not, this is the real mortals' world, below the clouds. ;)
That's right. A lightning fast application in 100% standard C++ is much better.
There's nothing inherently slow with the C++ standard libraries. And from what I know the Microsoft implementation is licenced from Dinkumware, a high quality provider. They wouldn't get away with a crappy implementation. And if Microsoft implemented it themselves I don't think they would have anything to gain from making their C++ standard libraries inferior on purpose to promote the MFC?
I've heard claims like this over and over again in forums and each time when the benchmarks are finally posted the only thing they prove conclusively is that the poster doesn't know what he's doing.Quote:
In my tests, STL containers are not always particularly fast. In many cases, the MFC containers are faster, sometimes dramatically so.