2011-09-23 3 views
2

나는C++ shallow/deep copy?

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

질문에 답하기 전에 "답변 게시"버튼을 눌렀습니다. [faq]를 읽으면 무엇이 좋은 질문인지 알 수 있습니다. –

+1

여기에는 의문의 여지가 없습니다. 질문은 물음표 (?)로 끝납니다. – abelenky

+0

유일한 것은 여기 C++입니다. – pmr

답변

0

정말 여기에 나열되지 않은 할당 연산자에 따라 다릅니다.

라인

output=a_attributes[index];

출력을 설정하기 위해 할당 연산자를 사용한다. 할당 연산자가 딥 복사를하면 딥 복사가됩니다.

0

할당 연산자에 과부하가 걸리지 않은 경우, 아니요, 얕은 복사본을 얻지 못합니다. output=a_attributes[index];을 할당하면 a_attributes[index] 사본을 만듭니다. 따라서 반환 된 값을 수정하면 a_attributes에 영향을주지 않습니다. 당신이 얕은 사본을 원하는 경우

, 당신은 하나 overload the assignment operator 할 것이다, 또는 다음 output=&a_attributes[index];에 마지막 줄을 변경, RELATION& *output에 인수를 변경 및 포인터를 전달하여, 참조 포인터를 전달합니다.

코드에 또 다른 문제가 있습니다. 문자열이 동일한 위치에 저장되어있는 경우에만 true를 반환하기 때문에 if(name==a_attributes[i].str_name) 행에있는 것과 같이 문자열을 ==과 직접 비교할 수 없습니다. 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 유형의 참조 객체가 아닌 함수에 전달하십시오.예를 들어

: 당신은 ptr_to_object 역 참조 지금이 시점에서 그래서

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 

을 할 수 있으며, 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_objectdelete을 호출하면 안됩니다. 포인터가 가리키는 개체를 "소유"하지 않고 반환되는 포인터가 new으로 할당 된 메모리 세그먼트의 시작을 가리 키지 않기 때문입니다. 또한 컨테이너 a_attribute이 객체를 처분하는 경우 (즉, std::map 또는 std::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 Relation&을 반환하는 const 과부하를 추가 할 수 있습니다.