2013-03-27 200 views
0

我在寫一個函數來將某個特定類的內容(一個二維直方圖,TH2F*)複製到另一個TH2F*。 Pratically,我希望能夠做到通過複製或通過引用傳遞指針

SafeCopy(in, out) 

其中in我輸入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指針。在後一種情況下,一些奇怪的事情發生了:如果我叫SafeCopy傳遞一個NULL h_out我得到這樣的輸出:

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); 

回答

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是複製那麼昂貴,你可能會通過類似疙瘩實現它,以便它可以便宜到移動,但仍然就像一個值類型。

如果你真的需要指針,那麼你應該使用智能指針,從來沒有擁有原始指針(擁有原始指針都非常保證使你的代碼異常不安全的,例如)。

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); 
+0

,我會記住它的時候我會做更復雜的東西:)現在我只是切換到更基本的東西來解決這個問題... – Blackphoenix 2013-03-28 09:02:05

+0

我只是出於好奇心寫了OP ...我只是不明白爲什麼通過引用傳遞poiter有一個不同的行爲通過拷貝傳遞的指針 – Blackphoenix 2013-03-28 09:03:41

+0

@Blackphoenix當你通過複製傳遞被調用函數和調用函數可以訪問兩個不同的對象;其中一個只是另一個的副本。調用函數對其對象的修改在調用上下文中不可見。但是,如果您可以同時獲取兩個上下文來訪問同一個對象,則另一個可以看到一個對象的修改。 – bames53 2013-03-28 15:36:10

0

您還沒有表現出調用代碼,但它聽起來像是問題來自SafeCopy(something, NULL)之類的東西。是的,不會工作。通過在指針和返回結果:

TH2F *SafeCopy(constTH2F *in, TH2F *out) { 
    if (!out) 
     out = whatever; 
    *out = *in; // or whatever... 
    return out; 
} 
+0

但是什麼原因造成的錯誤? – Beta 2013-03-27 18:29:35

+0

@Beta - NULL不是可修改的指針值。 – 2013-03-27 18:30:24

+0

等等......你的意思是把'NULL'作爲第二個參數,而不是一個值爲NULL的指針?那怎麼能編譯? – Beta 2013-03-27 18:32:30

0

如果我叫SafeCopy傳遞一個NULL h_out我得到這樣的輸出:
...
*編輯這是調用代碼:
TH2F * h_smearedMigration;
...
SmartCopy(h_migration,h_smearedMigration);

這不是一個NULL指針,這是一個未初始化的指針。它包含隨機垃圾,不可能是0x0。

+0

事實是,如果通過複製傳遞h_smearedMigration指針,它將顯示爲空指針。我也檢查了 // matrix smearing cout << h_smearedMigration << endl; \t SmartCopy(h_migration,h_smearedMigration); 並正確EHEH是你讓我想起了我的「使用智能指針!」一個同事......反正,非常感謝您的建議cout'ed爲0 – Blackphoenix 2013-03-27 18:40:42