1

使用する必要のある機能をテストするためのクラスを作成しました。基本的に、クラスは渡された文字列のディープ コピーを取得し、getter を介して使用できるようにします。Visual Studio 2012 を使用しています。プロジェクト設定で Unicode が有効になっています。

問題は、memcpy 操作によって切り捨てられた文字列が生成されることです。出力はそのようです。

THISISATEST: InstanceDataConstructor: Testing testing 123
Testing te_READY

ここで、最初の行は渡された TCHAR* 文字列のチェックであり、2 行目は割り当てられたメモリに memcpy 操作を入力した結果の出力です。期待される出力は次のとおりです。「テストテスト123」。

ここで何が間違っているのか誰でも説明できますか?

NB ここから #ifndef UNICODE typedefs を取得しました: 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());

渡す 3 番目の引数memcpy()は、コピーするバイト数です。
文字列が に格納されている単純な ASCII 文字列である場合、std::stringバイト数は ASCII 文字数と同じになります。

ただし、文字列がwchar_tUnicode UTF-16文字列の場合、Visual C++ ではそれぞれが2 バイトwchar_tを占有します (GCC の場合は異なりますが、これは VC++ でコンパイルされた Windows Win32/C++ コードなので、VC++ に注目しましょう)。したがって、の適切なサイズを考慮して、 のサイズ カウントを適切にスケーリングする必要があります。
memcpy()wchar_t

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

したがって、Unicode (UTF-16) モードでコンパイルすると、 thenTCHARは に展開されwchar_tsizeof(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 に答える