What faster?
And what containers is better to use in general MFC or STL?
P.S. I`m using MSVC.
Printable View
What faster?
And what containers is better to use in general MFC or STL?
P.S. I`m using MSVC.
std::vector. No comparison.
Jeff
... And what about CString and std::string?Quote:
Originally Posted by ncode
I `m going to rewrite some parts of my project to STL.
Well, here you might get some debate. std::string does not supply the complex interface that CString does.Quote:
Originally Posted by ncode
However, once you use a library like boost::string_algo, you'll be much better off with std::string.
My recommendation: use boost + std::string. It's more portable and powerful.
Jeff
In my experience STL is much much better than MFC.
IMO STL vector is superior.Quote:
Originally Posted by ncode
Also, the MFC CArray container has a serious bug when copying data (cilu would know more about this, since I believe he discovered the problem).
Regards,
Paul McKenzie
Well, as jfaust says, CString vs. std::string is debatable, but only if you plan to use the new version of CString that is templated and decoupled from the rest of MFC (CStringT is the templated class, and from what I remember, you can use it standalone from the other MFC classes).Quote:
Originally Posted by ncode
If you are using Visual C++ 6.0, then attempting to use CString and only CString without introducing other parts of MFC -- well it is very error-prone and not worth it. In the case of Visual C++ 6, use std::string.
Regards,
Paul McKenzie
Prior to considering the right choice based on efficiency and issues, comes the concern of portability.
If you are writing portable applications - you should try sticking to standard solutions otherwise you would consider other platform specific solutions.
Moreover, if it is an MFC application i.e. a framework based you should be better using framework based solutions (standard solutions are also a good choice but as long as they are not exposed to the public interface - they should be hidden as an implementation detail). Otherwise, you will almost see yourself overloading things for two types - CString and std::string or CArray and std::vector. You would also see yourself converting the types at all places where any cross interaction happens. These are un-necessary and can be avoided. If it is not especially an MFC application - you should be well off choosing a standard sequence.
Also, note that if you are working with wide-character type, you would use wstring.
In general, the STL is far better then MFC counter part.
However, CString not only provides better functions, but it's also more efficient then the std::string that comes with VC++ 6.0.
If portability is not an issue, I would recommend CString over std::string.
IMHO, there's nothing wroing with mixing STL and MFC, like std::vector<CString>
Also consider that it can be easier to port a ANSI MFC appliation using CString to a UNICODE application, then it would be if you were using std::string + std::wstring
Hello, in my assignment, I also use vector<CString> should this be better than CArrayString performancewise?
wine + vodka = headache
Once you are using the MFC class CString, then use the MFC CStringArray class as well.
This may increase a little bit the performance but it's not so important.
Important is the resulting more headache-free code.
Ask your teacher if I'm right... ;)
Yes of course, CArrayString performs worse than vector<CString>
But look, the vector has to construct their ctors at least twice
Carraystring is available/builtin class in the framework. Carraystring is composed also of many useful functions to easy-access and use. MFC is old but widely used framework at the present, rewriting the library to optimize everything would be what all developers are afraid of. The STL is newer and updated more frequently. It doesn't create much difference for moderate-mid sized application.
I would go for STL any time.
Even when you use MFC and is married to Windows it's better to use standard C++ as much as possible. Why? Becuse you minimize your dependency on a specific company that's why. Even if you're not planning to divorce MS it may suddenly decide to divorce you.
By the way, the original post was made in 2006. emailus resurrected this thread.Quote:
Originally Posted by VladimirF
Some points:
1) std::vector works fine in MFC codes
2) std::vector does not have "to construct their ctors at least twice"
(maybe the poster was trying to say something about when re-allocation
occurs ... but CArray needs to do re-allocation also)
3) vector has a richer array of public functions (pun intended). Also,
it works better with the <algorithm>
4) a vector has at least as good of performance as CArray ... and in
some cases much faster. The usual situation is when you are reading
data from a file and adding to the container (and you do not know
the number of data elements in the file). Below is code to simulate
this ...
Code:struct A
{
int x,y;
};
const int n = 1000000;
vector<A> v;
A a;
for (int i=0; i<n; ++i)
{
v.push_back(a);
}
"STL much faster than MFC" is just a legend.
Possible, that was true long time ago. :)
I have made some benchmarks for CStringArray vs. std::vector<CString> and the performance differences were small. For example, filling time resulted almost equal while sorting, a little bit faster for CStringArray (attached here is a screenshot as well as the VS2005 solution).
At least, if use a modern compiler and run under a modern computer, does not make sense anymore to mix STL in an MFC application for performance reasons.
On the other hand, as I already said many times before, mixing different libraries in a project makes the code harder to understand and maintain.
So again: DO NOT use STL in an MFC project if it's not absolutelly necessary.
I'd recommend the opposite. Prefer standard C++. Always use as much standard C++ as possible.
In an MFC project try to isolate MFC as much as possible. Try to make as big a part as possible free from MFC.
If you write in C++ let C++ rule, not some 3'rd party package.
Don't get confused by naming.
An MFC project is the Microsoft teminology for any C++ program which makes use of the MFC.
In reality it's a C++ project based on the MFC application framework. It's easy to get goobled up by the framework. It's the same if you use Qt.
Regardless of whether you're using MFC or Qt my advice is the same. Prefer standard C++ whenever possible. Don't allow the framework to take over your program. You're the captain. Fight mutiny with standard C++ or you'll lose the ship.
Now serious.
A little bit better saying is:
If for some reasons you are using STL in an MFC-based project, then put STL and MFC stuff in separate modules.
Looks like thoughts from someone with no or with not too much experience in software industry.
In reality, even you are a little programming genius, you'll get nothing trying to reinvent the wheel instead of using some already made stuff in a framework.
In contrary, your managers will complain for delayed deadlines, your colleagues will swear you for hard to understand and buggy code, and so on.
This is the real reality, Captain! ;)
Using an application framework is a strategic decision because once you've made your choise you're effectively stuck. But regardless of whether you're stuck with MFC or Qt or something else there's still plenty of room to decrease the coupling induced by the framework. One way is to prefer standard C++ over the framework and another is to isolate the framework as much as possible, like I suggested.
So it's not a question of reinventing the wheel. It's a question of preferring standard C++ whenever this is a reasonable option.
I still don't understand what you meant by 're-inventing the wheel'
Nobody said anything about doing that :confused:
The comment was that, if you have the choice between using MFC or STL, then STL was the better option.
1) "array size = 29979" ... try using array sizes that come up in many
scientific applications ... try an array size of 1,000,000 (or more)
2) It is not just the speed difference ... vector has a much richer array of
public interface functions and works better with <algorithm>
It's seasy to say something is better but a little bit harder to prove that's true.
See: http://www.codeguru.com/forum/showpo...5&postcount=19
However, I have no intention to flame (in an non-MFC forum :)).
Just few opinions of an old programmer which dealt many years both with MFC and STL (and many other frameworks and libraries).
If you consider I'm not right, no problem. Your choice... ;)
It's not so hard when the object is to try to make all generic and non-GUI code cross platform/ cross GUI framework agnostic. It means that a C++ coder coming to our company can work on our non-GUI code without having to have a good background in MFC, just standard C++.
No problem, can be done.
However, can you bet the results will be not the same? ;)
Im the most of MFC applications using <algorithm> is not necessary.
I have joined in this discuttion in the point CStringArray vs. std::string<CString>.
As seen in the uploaded examples, sorting CStringArray with qsort is faster than sorting std::vector<CString> with std::sort.
No problem, you can also sort CStringArray with std::sort and the result will be somewhere between the two.
So, any gain using vector and algorithm?
As can be seen, none.
There are two bold sentences I have posted in this thread.
- DO NOT use STL in an MFC project if it's not absolutelly necessary.
- If for some reasons you are using STL in an MFC-based project, then put STL and MFC stuff in separate modules.
Not any "MFC rocks while STL sucks". Have somebody seen something like that? ;)
MFC is good, STL is wonderful but IMHO, putting them together, in the same source code, like using std::vector<CString> instead of CStringArray, is not so brilliant idea.
No problem, it can be done but that doesn't really mean we do a better job.
1) Well, you also said that mixing MFC and STL was a "headache".
That might have been true a long time agao (pre version 5), but
since version 5 (~1997 ?) there are no problems mixing the two.
2) The problem with the MFC containers is that they do no even have
a consistent interface for looping thru the elements. You have to loop
thru a CList in a different way than thru a CArray. This means you need
to write duplicate code for doing such simple tasks as finding if an
element is in the container, or finding the largest element.
3) how many times has something like this been seen on the other board ?
And they want to know whay it will not compile.Code:class A
{
CArray< .... >;
// other
};
class B
{
CArray<A,...>
};
4) using qsort on a container of CString is technically undefined,
but since MS does it, I'll let it slide. But using qsort on other
non-POD elements still should not be done. Also, how are you
going to sort a CList ?
5) Here is a sample code ... feel free to publish your results
(also, not cheating by calling SetSize() or simuilar functions ....
remember my original post specifically stated the case where
you do not know how many elements before hand)
Code:#include "stdafx.h"
#include <iostream>
#include <vector>
#include <ctime>
#include <afxtempl.h>
using namespace std;
int main()
{
int n;
cout << "enter number of elements > ";
cin >> n;
clock_t start , finish;
CString s("Hello World");
start = clock();
/*
vector<CString> v;
for (int i=0; i<n; ++i)
{
v.push_back(s);
}
*/
CArray<CString,const CString &> v;
for (int i=0; i<n; ++i)
{
v.Add(s);
}
finish = clock();
cout << "number of ticks = " << finish - start << "\n";
return 0;
}
I find that quite surprising! I use STL algorithms all over the place - they save many, many lines of code. Unless of course you are not really using STL containers at all? If so, then you are really missing out.
There is even an advantage to mixing MFC and STL
For example...
Try doing that in so few lines with MFC alone. ;)Code:std::vector<CString> v;
// Sort
std::sort(v.begin(), v.end());
// Find the first instance of 3 consecutive repetitions of "Hello"
std::vector<CString>::const_iterator it = std::search_n(v.begin(), v.end(), 3, CString(_T("Hello")));
// Remove consecutive duplicate elements
std::erase(std::unique(v.begin(), v.end()), v.end());
// Reverse the order of first half
std::reverse(v.begin(), v.begin() + (v.size() / 2));
// And so on...
I can imagine hundred of applications that load "Hello World!" one millon (or more) times, having to be rewritten to gain one precious second. :D
Come on Philip! That could not be a serious benchmark example.
1) One second ???? Did you actually run it ? How many values
of n did you try ? What raethe results for n = 5,000,000 ?
n = 10,000,000 ? These are by no means un-reasonable
values for scientific applications.
2) Did you even bother reading my previous posts ? It simulates the case
where you do not know the number of elements before hand (such as
reading from a file or running a time-dependent simulation).
3) I still have not seen any proof of the so called "STL headaches"
4) Have you posted code for sorting CLIst yet ? Still waiting .... and waiting ...
and waiting ...
5) How about one funtion that find the largest element in a CArray or CList ?
Still waiting for that one function also.
I agree. But the bigger point (IMO) is that your code sample could be written using CArray and STL algorithms and not std::vector (using CArray::GetData). As a matter of fact, all of the algorithm functions can be used on MFC CArray.
I can't think of one non-trivial application, I don't care what the framework used is, that doesn't do some algorithm, whether it's searching, sorting, partitioning elements, etc. The problem I find with a lot of MFC programmers (and even STL programmers) is that they do not know this.
For the MFC programmer, they can keep using CArray, CStringArray, etc. and still use STL algorithms to do searching, sorting, partitioning, removing, shuffling, permutations, finding min/max, etc.
You can't do it in MFC, since algorithms do not exist in the MFC framework classes. The searches must be coded from scratch if no STL is used. This is no different than an STL container user who is not versed in algorithms -- they will also write all of this searching logic from scratch.Quote:
Try doing that in so few lines with MFC alone. ;)
The usual results from coding these functions from scratch is that the code is slower than using the algorithm function, or the code has subtle bugs, or the code is redundant (for example, writing the same general loop over and over again, with the only difference being the search criteria).
Regards,
Paul McKenzie
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.