WindowsXP(SP3) VC++2008使ってます。
c++初心者です。
Wave(音楽ファイル)のデータを読み込むプログラムを作成中なのですが、
Microsoft DirectX SDK (June 2010)ライブラリを参考にしてます。
その中で少し疑問に思うところがあったので、ご教授願えたらと思います。
// Allocate the waveformatex, but if its not pcm format, read the next
// word, and thats how many extra bytes to allocate.
if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM )
{
m_pwfx = ( WAVEFORMATEX* )new CHAR[ sizeof( WAVEFORMATEX ) ];
if( NULL == m_pwfx )
return 0;//( Lm_pwfx, E_FAIL );
// Copy the bytes from the pcm structure to the waveformatex structure
memcpy( m_pwfx, &pcmWaveFormat, sizeof( pcmWaveFormat ) );
m_pwfx->cbSize = 0;
}
else
{
// Read in length of extra bytes.
WORD cbExtraBytes = 0L;
if( mmioRead( m_hmmio,
( CHAR* )&cbExtraBytes, sizeof( WORD ) ) != sizeof( WORD ) )
return エラー;
m_pwfx = ( WAVEFORMATEX* )new CHAR[ sizeof( WAVEFORMATEX )+cbExtraBytes ];
if( NULL == m_pwfx )
return エラー;
// Copy the bytes from the pcm structure to the waveformatex structure
memcpy( m_pwfx, &pcmWaveFormat, sizeof( pcmWaveFormat ) );
m_pwfx->cbSize = cbExtraBytes;
// Now, read those extra bytes into the structure, if cbExtraAlloc != 0.
if( mmioRead( m_hmmio,
( CHAR* )( ( ( BYTE* )&( m_pwfx->cbSize ) ) + sizeof( WORD ) ),
cbExtraBytes ) != cbExtraBytes )
{
if( m_pwfx ){ delete m_pwfx; m_pwfx = 0; }
return エラー;
}
}
m_pwfx は WAVEFORMATEX* です。
WAVEFORMATEXやpcmWaveFormatとはMMSystem.hに定義されている構造体です。
質問したいことなのですが、
m_pwfx = ( WAVEFORMATEX* )new CHAR[ sizeof( WAVEFORMATEX ) ];
という文は
m_pwfx = new WAVEFORMATEX;
と何か違いがあるのでしょうか。
また、配列newしていると思うのですが、エラーの際にdelete m_pwfxという記述があり
ますが、これはdelete[] m_pwfxでなくていけないのではないでしょうか。
もしかしたらすごくお門違いな質問かもしれません。
よろしくお願いします。
> m_pwfx = ( WAVEFORMATEX* )new CHAR[ sizeof( WAVEFORMATEX ) ];
> という文は
> m_pwfx = new WAVEFORMATEX;
> と何か違いがあるのでしょうか。
前者は WAVEFORMATEX のコンストラクタを実行しません。
裏を返せば、WAVEFORMATES にコンストラクタが定義されていないなら、
意味としては(ほぼ)同じと言えます。
> また、配列newしていると思うのですが、エラーの際にdelete m_pwfxという記述があ
り
> ますが、これはdelete[] m_pwfxでなくていけないのではないでしょうか。
コンストラクト時との整合をとるため、正しくは:
CHAR* p = new CHAR[ sizeof( WAVEFORMATEX ) ];
m_pwfx = ( WAVEFORMATEX* )p;
...
delete[] p;
もしくは
m_pwfx = new WAVEFORMATEX();
...
delete m_pwfx;
επιστημη様、レスありがとうございます。
確かに!
この文だとコンストラクタは呼ばれませんよね。
気付きませんでした!
WAVEFORMATEXにコンストラクタやデストラクタはありませんが、
きっと製作する途中で何かあってこういう形になったんだろう、ということで
理解して先に進むことにします。
分かり易い説明で頭のもやもやが取れました。
ありがとうございました。
解決チェック忘れました
m_pwfx = ( WAVEFORMATEX* )new CHAR[ sizeof( WAVEFORMATEX )+cbExtraBytes ];
っていう文もあるから,このまま単純に
解決されていますんで余談なんですけどね。。。
m_pwfx = new WAVEFORMATEX();
と同じって理解でいいのかなぁ?
m_pwfx = ( WAVEFORMATEX* )new CHAR[ sizeof( WAVEFORMATEX )+cbExtraBytes ];
で
delete m_pwfx;
だと
普通に考えるとあれ?って思うね
こっから乗っかちゃいますけど
でも,new CHAR[size]ってsize文の連続した領域って考えると,
最終的には
::calloc(size,sizeof(CHAR))と同義?
ってことは,ヒープ領域の確保時のヘッダ?的には領域の最初に確保時のサイズがあるなら
ば
delete m_pwfx;で全て解放してくれそうな気もするし,
sizeof(WAVEFORMATEX)の分しか解放しないんじゃないか?って気もするし…
不思議。。。
要するに WAVEFORMATEX は可変サイズ構造体なわけで。
http://msdn.microsoft.com/ja-jp/library/cc371559.aspx
cbSize が非0のとき、追加データがあるってことで
> m_pwfx->cbSize = cbExtraBytes;
なので、この例は new char [] でも new WAVEFORMATEX でもうまくない。
可変長構造体をポータブルに実装するには malloc/calloc を使うしかないだろう。
new char[] は(初期値指定ない場合)0クリアされないので
calloc よりは malloc に近い。
移植性があって安全で無駄な0クリアしないのは
p_pwfx=(WAVEFORMATEX*)malloc(sizeof(WAVEFORMATEX)+cbExtraBytes);
free(p_pwfx);
まあもっとも VC++ の POD 配列の new/delete は malloc/free で実装されているので
話を VC++ に限定するなら実害はないわけだが。
new が NULL を返すことはない (nothrow な new を呼んでいないし) ので、
提示サンプルはなんだか非常に微妙な感じ。