2013-07-05 2 views
9

나는 동적으로 할당 된 배열에 포인트가있는 클래스가 있으므로 복사 생성자와 대입 연산자 함수를 만들었습니다. 복사 생성자와 대입 연산자 함수는 동일한 작업을 수행하므로 대입 연산자 함수에서 복사 생성자를 호출하지만 "error C2082: redefinition of formal parameter"을 얻습니다. Visual Studio 2012를 사용 중입니다.할당 연산자 함수에서 호출 복사 생성자

// default constructor 
FeatureValue::FeatureValue() 
{ 
    m_value = NULL; 
} 

// copy constructor 
FeatureValue::FeatureValue(const FeatureValue& other) 
{ 
    m_size = other.m_size; 
    delete[] m_value; 
    m_value = new uint8_t[m_size]; 

    for (int i = 0; i < m_size; i++) 
    { 
     m_value[i] = other.m_value[i]; 
    } 
} 

// assignment operator function 
FeatureValue& FeatureValue::operator=(const FeatureValue& other) 
{ 
    FeatureValue(other); // error C2082: redefinition of formal parameter 
    return *this; 
} 

답변

14

문제가되는 라인은 생각하는 바가 아닙니다. 실제로 변수 otherFeatureValue으로 선언합니다. 이는 생성자가 이름을 가지지 않고 직접 호출 할 수 없기 때문입니다.

연산자가 가상으로 선언되지 않은 한 생성자에서 안전하게 복사 할당 연산자를 호출 할 수 있습니다.

FeatureValue::FeatureValue(const FeatureValue& other) 
    : m_value(nullptr), m_size(0) 
{ 
    *this = other; 
} 

// assignment operator function 
FeatureValue& FeatureValue::operator=(const FeatureValue& other) 
{ 
    if(this != &other) 
    { 
     // copy data first. Use std::unique_ptr if possible 
     // avoids destroying our data if an exception occurs 
     uint8_t* value = new uint8_t[other.m_size]; 
     int size = other.m_size; 

     for (int i = 0; i < other.m_size; i++) 
     { 
      value[i] = other.m_value[i]; 
     } 

     // Assign values 
     delete[] m_value; 
     m_value = value; 
     m_size = size; 
    } 
    return *this; 
} 

이 뜻은 멋쟁이 작동하거나 복사 & 스왑 관용구에 대한 일반적인 지침을 Vaughn Cato's answer

+0

을 주셔서 감사합니다. 'value [i] = other.m_value [i]'? – stackunderflow

11

다른 방법과 마찬가지로 직접 생성자를 호출 할 수 없습니다. 당신이하고있는 일은 실제로 FeatureValue 타입의 other이라는 변수를 선언하는 것입니다. What is the copy-and-swap idiom?

이 더 나은하는 std::vector 대신 newdelete의를 사용

는 대입 연산자와 복사 생성자 사이의 중복을 피하기 좋은 방법에 대한 복사 및 스왑 관용구를 살펴 보자. 그런 다음 자신 만의 생성자 또는 할당 연산자를 작성할 필요가 없습니다.

+0

다시 한번 Bjoink입니다! –

+0

너희 둘 다 같은 일에 동시에 어떻게 대답했는지 그 기괴한. – Borgleader

+0

@Borgleader 당신이 더 이상하게 보일 수있는 것은 약 25 년 동안 Vaughn에 대해 잘 알고 있습니다. 그는 단지 나에 대해 몰랐다;) –

3

짧은 답변에서 제안 할 수 있습니다 - 그것을하지 않습니다.

세부 사항 :

// copy constructor 
FeatureValue::FeatureValue(const FeatureValue& other) 
{ 
    m_size = other.m_size; 
    delete[] m_value;  // m_value NOT INITIALISED - DON'T DELETE HERE! 
    m_value = new uint8_t[m_size]; 

    for (int i = 0; i < m_size; i++) 
    { 
     m_value[i] = other.m_value[i]; 
    } 
} 

// assignment operator function 
FeatureValue& FeatureValue::operator=(const FeatureValue& other) 
{ 
    FeatureValue(other); // error C2082: redefinition of formal parameter 
    return *this; 
} 

주 :

복사 생성자가 호출
  • ,이 복사되는 객체를 참조하여 새 개체를 구성,하지만 기본 생성자는 이전에 실행되지 않습니다 복사 생성자. 즉, 복사 생성자가 실행을 시작할 때 m_value에 불확정 값이 있음을 의미합니다. 할당 할 수는 있지만 정의되지 않은 동작이며 정의되지 않은 동작입니다. delete[] (UD!가 악화 될 수 있습니다. ;-)). 그래서, 그냥 delete[] 라인을 빠뜨리십시오. operator= 시도가 복사 생성자에서 기능을 활용하는 경우

다음, 먼저 m_value가 가리키는 기존 데이터를 공개해야하거나 유출됩니다. 대부분의 사람들은 다음과 같이 (을 파괴하는) 그렇게하려고 -이 당신을 위해 노력했는지 생각 :

FeatureValue& FeatureValue::operator=(const FeatureValue& other) 
{ 
    // WARNING - this code's not exception safe...! 
    ~FeatureValue(); // call own destructor 
    new (this) FeatureValue(other); // reconstruct object 
    return *this; 
} 

이것에 문제가 있음을 FeatureValue의 생성이 실패 할 경우 (예 : new 할 수 있기 때문에 메모리를 얻지 못하면 FeatureValue 객체는 유효하지 않은 상태로 남습니다 (예 : m_value이 공간을 가리킬 수 있음). 나중에 소멸자가 실행되고 delete[] m_value을 수행하면 정의되지 않은 동작이 발생합니다 (프로그램이 중단 될 수 있음).

정말 체계적으로 접근해야합니다 ...그것을 간단하고 깨끗

FeatureValue& FeatureValue::operator=(FeatureValue other) 
{ 
    swap(other); 
    return *this; 
} 

:하지만, 중 단계적으로 그것을 밖으로 쓰기, 혹은 ... 할 (쉬운 단지 std::swap()m_sizem_value을 보장 비 던지는 swap() 방법을 구현하고, 람를 사용하여 몇 가지 사소한 성능/효율성 문제가 있습니다. 피크 메모리 사용량 증가, 주변에 필요 이상으로 기존 m_value 배열을 유지

  • 을 ... 당신은 clear()를 부를 수 실제로, 대부분의 비 사소한 프로그램은 신경 쓰지 것 이것에 관해서는 dat 해당 구조에서 방대한 양의 데이터 (예 : PC 앱의 경우 수백 메가 바이트 또는 기가 바이트).

  • 메모리를 다시 사용하려고하지 않아도됩니다. 대신 other에 대해 다른 new (항상 메모리 사용량을 줄일 수 있지만 항상 가치있는 것은 아닙니다)을 수행해야합니다.

는 궁극적 이유는 별개의 복사 생성자와 operator=있을 수 있습니다 - 오히려 컴파일러는 자동으로 다른 하나를 만들 필요없이 - 일반적으로 - - 길에서 서로를 활용하여 최적의 효율적인 구현을 할 수 없다는 것입니다 너는 바랐다.

0

FeatureValue(other); 문은 실제로 복사 생성자를 호출하여 *this과는 아무런 관련이없는 새로운 Featurevalue 개체를 만듭니다.

관련 문제