1

我创建了一个类来测试我需要使用的一些功能。本质上,该类将获取传入字符串的深层副本,并通过 getter 使其可用。我正在使用 Visual Studio 2012。在项目设置中启用了 Unicode。

问题是 memcpy 操作产生了一个截断的字符串。输出是这样的;

THISISATEST: InstanceDataConstructor: Testing testing 123
Testing te_READY

其中第一行是对传入的 TCHAR* 字符串的检查,第二行是使用 memcpy 操作填充分配的内存的输出。预期的输出是;“测试测试 123”。

谁能解释这里有什么问题?

注意从这里得到#ifndef UNICODE typedef:how-to-convert-tchar-array-to-stdstring

#ifndef INSTANCE_DATA_H//if not defined already
#define INSTANCE_DATA_H//then define it

#include <string>

//TCHAR is just a typedef, that depending on your compilation configuration, either defaults to char or wchar.
//Standard Template Library supports both ASCII (with std::string) and wide character sets (with std::wstring).
//All you need to do is to typedef String as either std::string or std::wstring depending on your compilation configuration.
//To maintain flexibility you can use the following code:
#ifndef UNICODE  
  typedef std::string String; 
#else
  typedef std::wstring String; 
#endif
//Now you may use String in your code and let the compiler handle the nasty parts. String will now have constructors that lets you convert TCHAR to std::string or std::wstring.


class InstanceData
{
public: 
    InstanceData(TCHAR* strIn) : strMessage(strIn)//constructor     
        {
        //Check to passed in string
        String outMsg(L"THISISATEST: InstanceDataConstructor: ");//L for wide character string literal
        outMsg += strMessage;//concatenate message
        const wchar_t* finalMsg = outMsg.c_str();//prepare for outputting
        OutputDebugStringW(finalMsg);//print the message    

        //Prepare TCHAR dynamic array.  Deep copy.
        charArrayPtr = new TCHAR[strMessage.size() +1];
        charArrayPtr[strMessage.size()] = 0;//null terminate
        std::memcpy(charArrayPtr, strMessage.data(), strMessage.size());//copy characters from array pointed to by the passed in TCHAR*.

        OutputDebugStringW(charArrayPtr);//print the copied message to check    
        }

    ~InstanceData()//destructor
        {
            delete[] charArrayPtr;
        }

//Getter
TCHAR* getMessage() const
{
    return charArrayPtr;
}

private:
    TCHAR* charArrayPtr;
    String strMessage;//is used to conveniently ascertain the length of the passed in underlying TCHAR array.
};
#endif//header guard
4

2 回答 2

2

没有所有动态分配内存的解决方案。

#include <tchar.h>
#include <vector>
//...
class InstanceData
{
    public: 
        InstanceData(TCHAR* strIn) : strMessage(strIn),
        {   
            charArrayPtr.insert(charArrayPtr.begin(), strMessage.begin(), strMessage.end())
            charArrayPtr.push_back(0);   
        }

        TCHAR* getMessage()
        { return &charArrayPtr[0]; }

    private:
        String strMessage;
        std::vector<TCHAR> charArrayPtr;
};

这可以完成您的课程的工作,但主要区别在于它不执行任何手动动态分配代码。与具有动态分配的代码(缺少用户定义的复制构造函数和赋值运算符)不同,该类也是可安全复制的。

在几乎所有情况下,std::vector该类已经取代了必须做的事情。new[]/delete[]原因是vector将其数据存储在连续内存中,与调用new[].

于 2014-11-11T10:53:08.267 回答
1

请注意代码中的以下几行:

// Prepare TCHAR dynamic array.  Deep copy.
charArrayPtr = new TCHAR[strMessage.size() + 1];
charArrayPtr[strMessage.size()] = 0; // null terminate

// Copy characters from array pointed to by the passed in TCHAR*.
std::memcpy(charArrayPtr, strMessage.data(), strMessage.size());

要传递的第三个参数是要复制的字节memcpy()数。 如果字符串是存储在 中的简单 ASCII 字符串,则字节数与 ASCII 字符数相同。
std::string

但是,如果字符串是wchar_tUnicode UTF-16字符串,那么在 Visual C++ 中每个wchar_t占用2 个字节(与 GCC 不同,但这是用 VC++ 编译的 Windows Win32/C++ 代码,所以我们只关注 VC++)。因此,考虑到 a 的适当大小
,您必须正确缩放 的大小计数,例如:memcpy()wchar_t

memcpy(charArrayPtr, strMessage.data(), strMessage.size() * sizeof(TCHAR));

因此,如果您在 Unicode (UTF-16) 模式下编译,则TCHAR扩展为wchar_t, 并且sizeof(wchar_t)是 2,因此您的原始字符串的内容应该被正确地深度复制。

作为替代方案,对于 VC++ 中的 Unicode UTF-16 字符串,您也可以使用wmemcpy(),它被wchar_t视为其“复制单元”。因此,在这种情况下,您不必将尺寸因子按sizeof(wchar_t).


作为旁注,在您的构造函数中,您有:

InstanceData(TCHAR* strIn) : strMessage(strIn)//constructor     

由于strIn输入字符串参数,请考虑通过const指针传递它,即:

InstanceData(const TCHAR* strIn)
于 2014-11-11T10:54:38.620 回答