MFC: std::string vs CString?

21,695

Solution 1

I usually prefer to adapt my coding style to the framework I'm working in to be consistent with it. So when I work with MFC (which i haven't for a long time), I prefer the use of CString (and LPCTSTR as function arguments in public interface methods). When working with Qt I prefer QString and Qt's containers over STL containers and for everything not directly related to such a framework I use std::string as it's the standard C++ way of handling strings.

It doesn't make such a huge difference, since they all offer more or less equal functionality (and are easily convertible into each other) and when code is written for a certain framework, it depends on it anyway, so portability is not such a huge concern.

Just don't bother with plain char arrays! And by the way, try to pass objects by const reference (const std::string &caption) and not by value, as in C++ variables are not automatically references and copying a string can get quite expensive.

Solution 2

MFC was written with the expectation that you'd use CString. This is especially apparent when a function uses a parameter to return a string. For example, compare these two calls to GetWindowText:

CString s1;
wnd.GetWindowText(s1);

std::wstring s2(SOME_MAX, 0);
int len = wnd.GetWindowText(&s2[0], s2.size());
s2.resize(len);

Converting between the two isn't bad though, so you might compromise by using std::wstring for most things and a temporary CString when necessary.

CString s3 = s2.c_str();
std::wstring s4 = s1;

Edit: There may be a way to automate the temporary CString. Fair warning, this is a complete hack. I haven't tried this, so no guarantees - you'll probably get warnings about binding a temporary to a non-const reference, but you can turn those off.

class PopString : public CString
{
public:
    PopString(std::wstring & final) : m_final(final)
    {
    }

    ~PopString()
    {
        m_final = (PCTSTR) *this;
    }
private:
    PopString(const PopString &) {}  // private copy constructor to prevent copying
    PopString & operator=(const PopString &) {}  // private copy operator

    std::wstring & m_final;
};

std::wstring s5;
wnd.GetWindowText(PopString(s5));

Solution 3

If you care for portability and you're using C++ use std::string. No point going low-level with char arrays if you don't need to. If you don't care for portability and the platform-provided strings provide more of the features you need, by all means, use them. They might actually be more optimized for the platform.

Solution 4

Do not use CString. It uses a COW implementation which is very vulnerable to things like threading. Do not use char* or LPCTSTR (which is just const char* or const wchar_t* under a different name), as they do not manage their own memory. Use a std::string for 8-bit codepoints or std::wstring for 16-bit codepoints on Windows (32bit for Unix).

Share:
21,695
User
Author by

User

Updated on May 25, 2020

Comments

  • User
    User almost 4 years

    Using C++ with MFC. Coming from a C# background I typically just use string for all, well, strings. I use them for class members, method parameters, and method return values.

    Now in C++ I've got std::string, CString, char *, LPCTSTR, and more. As I design my data members, method parameters, and method return values which type(s) should I be using? Ease of use is important and CString seems to offer that but my instinct is toward portable standards although portability is pretty low on my list of priorities (now). Also, I don't like the c semantics of creating string buffers and passing them into methods and functions.

    I think from an immediate ease of coding perspective CStrings probably have the edge. But, overall, what is the "high code quality" way to do this?

    EDIT:

    I'm especially concerned about the interface points in my code (i.e. method parameters and return values). E.g.:

    Shape::SetCaption(const char *caption) {...}
    
    Shape::SetCaption(CString caption) {...}
    
    Shape::SetCaption(std::string caption) {...}
    
    Shape::SetCaption(std::wstring caption) {...}