TCHAR数组的深度副本被截断
Deep copy of TCHAR array is truncated
我创建了一个类来测试我需要使用的一些功能。本质上,该类将获取传入字符串的深层副本,并通过getter使其可用。我正在使用Visual Studio 2012。Unicode已在项目设置中启用。
问题是memcpy操作产生了一个截断的字符串。输出是这样的;
THISISATEST: InstanceDataConstructor: Testing testing 123
Testing te_READY
其中第一行是对传入的TCHAR*字符串&第二行是用memcpy操作填充分配的内存的输出。预期输出为;"测试123"。
有人能解释一下这里出了什么问题吗?
注意:从这里得到了#ifndef UNICODE typedefs:如何将tchar数组转换为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
一个没有所有动态分配内存的解决方案。
#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[]
没有什么不同。
请注意代码中的以下几行:
// 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字符串,那么在Visual C++中,每个wchar_t
占用2个字节(与GCC不同,但这是用VC++编译的Windows Win32/C++代码,所以我们只关注VC++)
因此,考虑到wchar_t
的适当大小,您必须适当缩放memcpy()
的大小计数,例如:
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)
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- OpenGL在启用深度测试时不会丢弃我的碎片
- 用callgrind追踪不必要的副本
- 关于:C++中异常对象的范围:为什么我没有得到副本?
- 在为LINUX创建共享库时,如何避免STL的私有/弱副本
- 检查注册表项是否链接到(或副本)另一个注册表项
- C++尝试深度复制唯一指针时出现内存访问冲突
- 为什么构建目录中新构建的共享库与安装目录中的副本具有不同的依赖项集?
- C++基于范围的 for 循环和元素副本
- 试图找到二叉树的深度
- 创建提升::shared_ptr的深层副本
- 如何从构造函数副本 T(const T&)调用对象 T?
- 副本初始化的默认模板参数推导
- C++深浅的副本
- 操纵安卓相机的深度图导致应用程序崩溃
- 深度值没有意义 R200 相机
- 将相同共享指针的副本存储在不同的向量中是否是一种好的做法?
- 对如何制作双链表的深度副本感到困惑?
- 特征:如何制作矩阵的深度副本
- TCHAR数组的深度副本被截断