0

特定のクラス (2D ヒストグラムTH2F*) の内容を別のクラスにコピーする関数を作成していTH2F*ます。実際には、私はできるようになりたいです

SafeCopy( in, out )

whereinは私の入力TH2F*outあり、私の目的地TH2F*です。特に、事前に割り当てられていないSafeCopy場合でも動作できるように実装したいと考えています。out最初の例では、この(間違った)方法で関数を実装しました

void SafeCopy( const TH2F * h_in, TH2F *h_out )
{
    cout << "SafeCopy2d: output histogram address is " << h_out << endl;
    if( h_out != NULL )
    {
        cout << "SafeCopy2d: h_out has been identified as non-zero pointer\n"; 
        (*h_out) = *h_in; // I'm making use of the copy-constructor
                          // it wouldn't work if h_out == NULL 
    }
    else 
    {
        cout << "SafeCopy2d: h_out has been identified as null pointer\n";
        h_out = new TH2F( *h_in );
        cout << "SafeCopy2d: h_out address is now " << h_out << endl;
    }
}

そして出力は

SafeCopy2d: output histogram address is 0x0
SafeCopy2d: h_out has been identified as null pointer
SafeCopy2d: h_out address is now 0xblahblah

しかし、もちろんこれは機能しませんでした。関数を終了するとき、参照ではなくコピーで渡したため、「実際の」ポインター h_out がまだ 0 だったからです。次に、関数のプロトタイプを(実装を変更せずに)変更しました

void SafeCopy( const TH2F * h_in, TH2F *&h_out )

h_out ポインターを参照で渡すため。この後者の場合、何か奇妙なことが起こります。NULL h_out を渡して SafeCopy を呼び出すと、次の出力が得られます。

SafeCopy2d: output histogram address is 0x*a non-zero value*
SafeCopy2d: h_out has been identified as non-zero pointer

私の質問は、h_out をコピーで渡すと、NULL ポインターとして正しく認識されるのに、参照で渡すと非ゼロとして表示されるのはなぜですか?

編集 これは呼び出しコードです:

//TH2F * h_migration is created and filled previously in the program
TH2F * h_smearedMigration;//  
for (int ntoy=0; ntoy < NTOY; ntoy++ ) {

         //matrix smearing
    SmartCopy( h_migration, h_smearedMigration ); //copy the original matrix to a temporary one
    RunToy( h_smearedMigration ); //smear the matrix
...

みたいなことは避けたい

h_smearedMigration = SmartCopy( h_migration, h_smearedMigration );
4

3 に答える 3

0

呼び出しコードは表示されていませんが、問題は次のようなものから発生するようSafeCopy(something, NULL)です。うん、うまくいかない。ポインターを渡し、結果を返します。

TH2F *SafeCopy(constTH2F *in, TH2F *out) {
    if (!out)
        out = whatever;
    *out = *in; // or whatever...
    return out;
}
于 2013-03-27T18:26:33.260 に答える
0

NULL h_out を渡して SafeCopy を呼び出すと、次の出力が得られます:
...
* edit これは呼び出しコードです:
TH2F * h_smearedMigration;
...
SmartCopy( h_migration, h_smearedMigration );

これは NULL ポインターではなく、初期化されていないポインターです。ランダムなジャンクが含まれており、0x0 である可能性は低いです。

于 2013-03-27T18:37:44.777 に答える
0

まず、ポインタを使用している理由がまったくわかりません。理想的には、オブジェクトを直接保持したいだけです。次に、コピーするための特別な規則は必要ありません。

TH2F RunToy(TH2F const &in);

//TH2F h_migration is created and filled previously in the program
for (int ntoy=0; ntoy < NTOY; ntoy++ ) {
    TH2F h_smearedMigration = RunToy(h_migration);

コピーするのにコストがかかる場合TH2Fは、pImple のようなものを介して実装することで、安価に移動できますが、それでも値型のように機能します。

本当にポインターが必要な場合は、スマート ポインターを使用し、生のポインターを所有しないようにする必要があります (例えば、生のポインターを所有すると、コードが例外的に安全でなくなることがほぼ保証されます)。

void RunToy(std::unique_ptr<TH2F> in_out);

void SafeCopy(TH2F const &in, std::unique_ptr<TH2F> &out)
{
    if(h_out) {
        *out = in; // copy assignment
    } else {
        out = make_unique<TH2F>(h_in); // copy construction
    }
}

for (int ntoy=0; ntoy < NTOY; ntoy++ ) {
    std::unique_ptr<TH2F> h_smearedMigration;
    SmartCopy(h_migration, h_smearedMigration);
    RunToy(h_smearedMigration );

もちろん、通常、SmartCopyコピー代入とコピー構築のどちらを使用するかを動的に決定する関数は必要ありません。オブジェクトを既に割り当てているかどうかに基づいて、何が必要かを知る必要があります。

// std::unique_ptr<TH2F> h_migration is created and filled previously in the program
for (int ntoy=0; ntoy < NTOY; ntoy++ ) {
    auto h_smearedMigration = make_unique<TH2F>(*h_migration);
    RunToy(h_smearedMigration);
于 2013-03-27T19:24:39.537 に答える