我可以重载CArchive<<运算符使用std :: string?

时间:2011-09-16 14:49:35

标签: c++ stl mfc

我在我的MFC应用程序中使用std :: string,我想将它存储在doc的Serialize()函数中。我不想将它们存储为CString,因为它在那里写了自己的东西,我的目标是创建一个我知道格式的文件,并且可以被其他应用程序读取而不需要CString。所以我想把我的std :: strings存储为4个字节(整数)的字符串长度,然后是包含该字符串的那个大小的缓冲区。

void CMyDoc::Serialize(CArchive& ar)
{
    std::string theString;

    if (ar.IsStoring())
    {
        // TODO: add storing code here
        int size = theString.size();
        ar << size;
        ar.Write( theString.c_str(), size );

    }
    else
    {
        // TODO: add loading code here
        int size = 0;
        ar >> size;
        char * bfr = new char[ size ];
        ar.Read( bfr, size);
        theString = bfr;
        delete [] bfr;
    }
}

上面的代码不是很好,我必须分配一个临时bfr来读取字符串。首先,我可以直接将字符串读入std :: string而不使用临时缓冲区吗?其次,我可以重载&lt;&lt;缓冲区为std :: string / CArchive所以我可以简单地使用ar&lt;&lt; theString?总的来说有一种更好的方法来使用CArchive对象读/写std :: string吗?

5 个答案:

答案 0 :(得分:1)

尝试:

theString.resize(size);
ar.Read(&theString[0], size);

技术上&theString[0]不能保证指向连续的字符缓冲区,但是C ++委员会进行了一项调查,发现所有现有的实现都是这样的。

答案 1 :(得分:1)

您可以从stl字符串构建一个inplace CString并序列化它。类似的东西:

CString c_string(my_stl_string.c_str();
ar << c_string;

你可以把它放在一个全局的operater重载中,这样你就可以

ar << my_c_string;

来自任何地方,例如:

CArchive& operator<<(CArchive rhs, string lhs) {
    CString c_string(lhs.c_str());
    rhs << c_string;
}

答案 2 :(得分:1)

由于各种原因,最好将数据写为CString,但是如果你必须将你的String(m_sString)转换为ASCII字符串,那么这样的东西可能对你有用......

void myclass::Serialize(CArchive & ar)
{
    CHAR* buf;
    DWORD len;
    if (ar.IsStoring()) // Writing
    {
        len = m_sString.GetLength(); // Instead of null terminated string, store size.
        ar << len;
        buf = (CHAR*)malloc(len);
        WideCharToMultiByte(CP_UTF8, 0, m_sString, len, buf, len, NULL, NULL); // Convert wide to single bytes
        ar.Write(buf, len); // Write ascii chars
        free(buf);
    }
    else // Reading
    {
        ar >> len;
        buf = (CHAR*)malloc(len);
        ar.Read(buf, len); // Read ascii string
        MultiByteToWideChar(CP_UTF8, 0, buf, len, m_sString.GetBufferSetLength(len), len); // Convert ascii bytes to CString wide bytes
        free(buf);
    }
}

答案 3 :(得分:0)

如果您正在使用仅适用于c风格字符串的库,则无法安全地write directly to the std::string。该问题在C ++ 0x中得到修复。 像

这样的东西
// NOT PORTABLE, don't do this
theString.resize(size);
ar.Read( const_cast<char *>(theString.c_str(), size);

可能会有效,但它可能会在以后创建一些微妙的,难以跟踪的错误。 当然,你的问题意味着你已经分析了你的代码,并发现创建缓冲区和复制数据两次实际上是代码中的瓶颈。如果你还没有,那么你不应该担心效率低下。

答案 4 :(得分:0)

我认为您可能违反STL指南并且继承 std::string并添加您自己的缓冲区getter / setter。然后覆盖std :: string的复制构造函数并转移缓冲区的所有权。