我已经创建了一个类来测试我需要使用的一些功能。本质上,该类将获取传入的字符串的深层副本,并通过getter使其可用。我使用的是Visual Studio 2012.在项目设置中启用了Unicode。
问题是memcpy操作产生了截断的字符串。输出就是这样;
THISISATEST: InstanceDataConstructor: Testing testing 123
Testing te_READY
其中第一行是检查传入的TCHAR *字符串&第二行是使用memcpy操作填充分配的内存的输出。预期产量为; “测试测试123”。
有谁可以解释这里有什么问题?
N.B。从这里得到#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
答案 0 :(得分: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[]
没什么不同。
答案 1 :(得分: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()
的第三个参数是要复制的字节的计数。
如果字符串是存储在std::string
中的简单ASCII字符串,则字节数与ASCII字符数相同。
但是,如果字符串是 wchar_t
Unicode UTF-16 字符串,那么每个wchar_t
在Visual C ++中占用 2个字节(带有GCC的东西是不同的,但这是用VC ++编译的Windows Win32 / C ++代码,所以我们只关注VC ++。)
因此,考虑到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
视为&#34;副本单元&#34;。因此,在这种情况下,您不必将尺寸因子缩放sizeof(wchar_t)
。
作为旁注,在你的构造函数中你有:
InstanceData(TCHAR* strIn) : strMessage(strIn)//constructor
由于strIn
是输入字符串参数,请考虑通过 const
指针传递它,即:
InstanceData(const TCHAR* strIn)