2011-09-23 131 views
2

我有這個功能C++淺/深層複製?

int getrelation(string name, RELATION& output){ 

     bool found=0; 
     int index=0; 
     for(int i=0;i<a_attributes.size();i++){ 
      if(name==a_attributes[i].str_name){ 
       found=1; 
       index=i; 
      } 
     } 
     if(!found){ 
      printf("relation not found"); 
      return 1; 
     } 
     output=a_attributes[index]; 

     return 0; 
    } 

關係是一類 a_attributes是關係的一個載體。

它應該返回對關係對象的引用。在調用getrelation()之後,如果我更改輸出值,那麼a_attributes[index]的值也應該更改,因爲這是淺拷貝,對嗎?

+1

我想你在問你問題之前先按下了「Post Answer」按鈕。閱讀[常見問題]以瞭解什麼是一個很好的問題。 –

+1

這裏沒有問題。問題以問號(?)結尾。 – abelenky

+0

這裏唯一的C++就是參考。 – pmr

回答

0

這實際上取決於你的賦值運算符,這裏沒有列出。

output=a_attributes[index];

將使用賦值操作符來設置輸出。如果該賦值運算符進行深度複製,則獲得深層副本。

0

如果你沒有重載賦值操作符,那麼不,你不會得到淺拷貝。當您分配output=a_attributes[index];時,您正在製作a_attributes[index]的副本。因此,對返回值的任何修改都不會影響a_attributes

如果你想有一個淺拷貝,那麼你就必須要麼overload the assignment operator,或通過引用傳遞一個指針,通過改變參數RELATION& *output,並傳遞一個指針,那麼最後一行更改爲output=&a_attributes[index];

你的代碼還有另一個問題。您不能直接將字符串與==進行比較,就像您在線路if(name==a_attributes[i].str_name)中所做的那樣,因爲只有字符串存儲在相同位置時它纔會返回true。你需要使用類似strcmp()的東西。

0

不,因爲你在這裏是一個深層複製。 output參數是對類RELATION的某個對象的引用。因此,如果您在getrelation函數中更改該對象,則用戶會注意到這些更改,因爲您更改了引用的對象。但是,在此行上 - output=a_attributes[index];本質上調用對象output的複製賦值運算符,該運算符將a_attributes[index]返回的對象中的每個字段的深度副本複製到output引用的對象中,除非複製賦值運算符被重載並執行了其他操作。這基本上是因爲你不能改變引用的值 - 例如,它不能引用一個對象並最終引用另一個對象。爲了達到你想要的效果(如果我找對了),你必須傳遞一個指向指向對象的指針的指針(或者指向一個指針的指針),然後你可以通過去引用它來改變指向該對象的指針。像這樣:

int getrelation(string name, RELATION **output){ 
     bool found=0; 
     int index=0; 
     for(int i=0;i<a_attributes.size();i++){ 
      if(name==a_attributes[i].str_name){ 
       found=1; 
       index=i; 
      } 
     } 
     if(!found){ 
      printf("relation not found"); 
      return 1; 
     } 
     *output= &a_attributes[index]; 
     return 0; 
    } 

希望它有幫助!

0

否...如果要獲取對輸出對象的引用,請將RELATION類型的引用指針傳遞給該函數,而不是RELATION類型的引用對象。

例如:現在這麼

RELATION* ptr_to_object = NULL; 
string argument_name; 
//...more code to initialize argument_name 

if (getrelation(argument_name, ptr_to_object) == 1) 
{ 
    //...handle error condition 
} 

//now ptr_to_object points to your a_attribute[index] object 

在這一點上,你可以解引用ptr_to_object,你會在a_attribute[index]獲得對象:

int getrelation(string name, RELATION*& output) 
{ 
    bool found=0; 
    int index=0; 
    for(int i=0;i<a_attributes.size();i++){ 
     if(name==a_attributes[i].str_name){ 
      found=1; 
      index=i; 
     } 
    } 
    if(!found){ 
     printf("relation not found"); 
     return 1; 
    } 
    output = &(a_attributes[index]); //take the address-of object 

    return 0; 
} 

你會再打電話給你的功能,像這樣。然後可以通過取消引用指針來更改該對象的屬性。唯一的警告是你不應該在ptr_to_object上調用delete,因爲它沒有「擁有」被指向的對象,並且返回的指針不指向分配了new的內存段的開始。此外,如果容器a_attribute處置該對象(即,如果它是std::mapstd::vector),則指針將指向無效的存儲器位置。所以您必須確保容器不會出現您用作對象引用的指針。

0

下面是一些更習慣的C++,雖然返回實際的迭代器也可能是一個好主意。

struct rel_by_name : public std::binary_function<const std::string&, const RELATION&, bool> { 
    bool operator()(const std::string& s, const RELATION& rel) { 
    return s == rel.str_name; 
    } 
}; 

RELATION& getrelation(const std::string& name) { 
    std::vector<RELATION>::iterator it = std::find_if(a_attributes.begin(), a_attributes.end(), 
                std::bind1st(rel_by_name(), name)); 
    if(it == a_attributes.end()) { 
    //not found, report error by throwing or something 
    } 
    else { return *it; } 
} 

您可能想要添加一個const超載返回const Relation&