【问题标题】:MFC: std::string vs CString?MFC:std::string vs CString?
【发布时间】:2011-09-01 07:34:45
【问题描述】:

在 MFC 中使用 C++。来自 C# 背景,我通常只对所有字符串使用字符串。我将它们用于类成员、方法参数和方法返回值。

现在在 C++ 中,我有 std::string、CString、char *、LPCTSTR 等。当我设计我的数据成员、方法参数和方法返回值时,我应该使用哪种类型?易用性很重要,CString 似乎提供了这一点,但我的直觉是倾向于可移植标准,尽管可移植性在我的优先级列表中非常低(现在)。另外,我不喜欢创建字符串缓冲区并将它们传递给方法和函数的 c 语义。

我认为从直接易于编码的角度来看,CStrings 可能具有优势。但是,总体而言,“高代码质量”的方法是什么?

编辑:

我特别关心代码中的接口点(即方法参数和返回值)。例如:

Shape::SetCaption(const char *caption) {...}

Shape::SetCaption(CString caption) {...}

Shape::SetCaption(std::string caption) {...}

Shape::SetCaption(std::wstring caption) {...}

【问题讨论】:

  • @Christian:为在 MFC 中实现且必须与其紧密集成的平台编写插件。我试图走 Qt 的道路,但 Qt/MFC 集成是一场艰苦的战斗。如果是一个选项,我会选择 C#。
  • 同意 Christian Rau 的评论。 MFC 不是对开发人员友好的框架。 QT 是一种让 GUI 变得更简单的方法。

标签: c++ string mfc cstring stdstring


【解决方案1】:

不要使用 CString。它使用了一个很容易受到线程之类的东西的 COW 实现。不要使用char*LPCTSTR(只是const char*const wchar_t* 使用不同的名称),因为它们不管理自己的内存。在 Windows 上使用 std::string 用于 8 位代码点或 std::wstring 用于 16 位代码点(Unix 为 32 位)。

【讨论】:

  • 它不像 std 字符串是线程安全的。但是 -1 因为使用 mfc CString 通常是要走的路。
  • @John Dibling:std::string 是线程安全的,而 CString 不是。如果你有两个独立的std::string,你可以保证它们在两个线程上使用是安全的。 CString 不能这样说。
  • @ChristianRau :该问题仅在 C++11 中在标准中正式修复,但该问题已在五年前的缺陷报告 530 中正式确认并且从那时起(如果不是更早的话)已经在每个主要的标准库实现中实现。
  • @DeadMG:是否有文章或 SO 问题的链接,即不能在不同线程中独立使用 CString 的 2 个实例?如果真的是这样的话,听起来很严重。是某种特殊情况,还是普遍情况?我将使用 VS 6.0。有没有更新版本的 VS 可以解决这个问题?
  • 线程规则为explicitly spelled out。如果这对您来说还不够好,请实现自定义同步,或使用不同的字符串类。使用 MFC 代码几乎总是最好使用CString's。更重要的是,如果您也使用 COM。我还将假设所有出现的 "codepoints" 都应为 "code units"。也许你至少可以解决这个问题。
【解决方案2】:

我通常更喜欢让我的编码风格适应我正在使用的框架,以保持一致。因此,当我使用 MFC(我已经很久没有使用 MFC 了)时,我更喜欢使用 CString(和 LPCTSTR 作为公共接口方法中的函数参数)。在使用 Qt 时,我更喜欢 QString 和 Qt 的容器而不是 STL 容器,对于与此类框架不直接相关的所有内容,我使用 std::string,因为它是处理字符串的标准 C++ 方式。

这并没有太大的区别,因为它们都提供或多或少相同的功能(并且很容易相互转换),并且当为某个框架编写代码时,它无论如何都取决于它,所以可移植性是不是那么大的问题。

只是不要为普通的 char 数组而烦恼!顺便说一句,尝试通过 const 引用 (const std::string &caption) 而不是按值传递对象,因为在 C++ 中,变量不会自动引用,并且复制字符串会变得非常昂贵。

【讨论】:

  • 当我需要一个临时缓冲区来存储某些东西时,我有时会使用普通的 char 数组,尽管 vector<char> 也很幸运。
  • 有道理,但是即使在您构建的静态库中,您会使用 CString 以供 MFC 项目使用吗?
  • @User 如果库本身不使用或不依赖于 MFC 并且可能与另一个项目一起使用,那么绝对不会。但如果它无论如何都绑定到你的项目,我不太确定。我会在与 MFC 没有直接关系的所有内容中使用 std::string,以实现更好的代码重用和灵活性。
【解决方案3】:

编写 MFC 时期望您使用 CString。当函数使用参数返回字符串时,这一点尤其明显。例如,比较这两个对 GetWindowText 的调用:

CString s1;
wnd.GetWindowText(s1);

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

不过,两者之间的转换还不错,因此您可能会在大多数情况下使用 std::wstring 并在必要时使用临时 CString 来妥协。

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

编辑:可能有一种方法可以自动化临时 CString。公平的警告,这是一个完整的黑客。我还没有尝试过,所以不能保证 - 您可能会收到有关将临时对象绑定到非常量引用的警告,但您可以将其关闭。

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));

【讨论】:

    【解决方案4】:

    如果您关心可移植性并且您正在使用 C++,请使用 std::string。如果您不需要,使用char 数组进行低级处理是没有意义的。如果您不关心可移植性并且平台提供的字符串提供了您需要的更多功能,请务必使用它们。它们实际上可能针对该平台进行了更多优化。

    【讨论】:

    • 技术上,使用std::basic_string<>,而不仅仅是std::string。即,在 Windows 上,std::wstring 更可能是
    • @ildjarn,你的意思是说std::basic_string<TCHAR>
    • @MarkRansom :不,我指的是整个std::basic_string<> 类模板,而不是专门针对std::basic_string<char> 专业化(又名std::string)。
    • “便携”+“mfc”=矛盾修饰法
    猜你喜欢
    • 2012-10-01
    • 1970-01-01
    • 2019-01-25
    • 1970-01-01
    • 1970-01-01
    • 2018-03-20
    • 2020-06-11
    • 1970-01-01
    • 2012-11-04
    相关资源
    最近更新 更多