2012-03-29 2 views
0

복사 생성자가없는 클래스가 있거나 operator=이 오버로드되었습니다. 코드는 꽤 큰하지만 문제는이 의사 코드 주위 :클래스에 복사 생성자 문제가 없습니다?

ClassA object1(x,y); 
object1.add(z) 
myVector.push_back(object1); 

//Now when I retrieve from myVector and do add it 
// apparently creates another object 
myVector.at(index).add(z1); 

나는 그것이 의사 코드입니다 말했듯이. 전문가들이 이해할 수 있기를 바랍니다.

그래서, 지금해야 될 복사 생성자의 필요성은, ClassB가 B는이 릴리스의 새로운 데이터 멤버이기 때문에

Class ClassA { 

private: 
    int x; 
    string y; 
    ClassB b; 
    vector<int> i; 
public: 
    int z; 

} 

를 ClassA는 (물론 모든 데이터 멤버 포함)과 같다? 답변 해 주신 모든 분들께 감사드립니다.

Class ClassB { 
private: 
vector<ClassC*> c; 
Class D 
} 
Class ClassC { 
private: 
vector<ClassE*> e; 
} 
Class ClassD{ 
private: 
vector<ClassF*> f; 
} 

그러면 ClassE와 ClassF는 int 및 string과 같은 기본 유형을 갖습니다.

+0

(게시물에 사용자 이름을 표시하려면 자동 생성 된 userXYZ 이름 대신 원하는 이름으로 프로파일을 채우십시오. 게시물에 서명하지 마십시오.) – Mat

+0

Welcome to Stack Overflow! SO는 질의 응답 사이트입니다. 특정 질문이 있으십니까? –

답변

1

at()을 사용하여 개체를 검색 할 때 새 개체가 만들어지지 않습니다. at()은 그것에 대한 참조를 리턴합니다. 새 개체는 push_back()을 수행 할 때 만들어진 입니다. 접근 가능한 복사 생성자 또는 할당 연산자가없는 경우 개체를 벡터에 넣을 수 없습니다. 공식적으로 정의되지 않은 동작이지만, 적어도 벡터를 사용하면 (실제로했듯이) 실제로는 이 컴파일되지 않습니다. 대부분 컴파일러가 기본값을 생성하게됩니다. 실제 개체 유형을 보지 않고도 이 적절한 지 여부를 말할 수는 없습니다. 객체 유형에 표준 라이브러리의 유형 및 유형 (iostream 내용 인 및 auto_ptr — 제외)과 을 사용하는 경우 스레딩 내용 만 포함하면 컴파일러에서 생성자 생성자와 할당이 생성되어야합니다. be 확인하십시오. 클래스에 생성자에 할당 한 메모리에 대한 포인터가 포함되어 있으면 거의 확실하지 않습니다.

+0

ClassA에는 사용자 정의 클래스가 있습니다. 그래서 ClassA에 대한 복사 생성자와 ClassA의 일부인 다른 사용자 정의 클래스를 만들 것을 제안합니까? 너의 도움에 모든 감사를 표한다. – Jay

+0

주목할 또 다른 사항. 지금까지 ClassA는 데이터 형식으로 기본 형식과 벡터 만을 가지고있었습니다. 따라서 나는 복사 생성자가 없거나 정의되지 않은 상태에서이 모든 문제에 직면하지 않았습니다. 이번 릴리스에서는 새로운 사용자 정의 ClassB가 데이터 멤버로 포함되었습니다. – Jay

+0

그래서 ClassA는 다음과 같이 보입니다 (물론 모든 데이터 멤버가 포함되지는 않습니다). – Jay

0

push_back은 값으로 매개 변수를 수신 할 때 복사본을 만듭니다. 복사 생성자를 사용하고 싶지 않은 경우 벡터를 객체에 대한 포인터의 벡터로 정의하고 대신 포인터를 누릅니다.

+1

단지 nit이지만, 'push_back'은 매개 변수를 참조로받습니다. (벡터에 실제로 객체를 삽입 할 때 사본을 생성합니다.) –

+0

또한 참조 컨테이너를 가질 수 없습니다. – stefaanv

0

저장된 값이 사본이기 때문에 검색 할 때 임시로 만들어야합니다.

0

복사 생성자를 사용하는 것이 아니라 일반 구조체 복사본을 사용하고 있는지 의심 스럽습니다.

myVector.at(index) 
이 경우

반환 ClassA하지 ClassA &

당신은에 의해이 문제를 해결 할 수 있어야한다 : 나는 함께 비주얼에 놀라운 결과를 가지고 약간의 테스트를 넣어

ClassA & refObj = myVector.at(index); 
refObj.add(z1); 

사진관.

class Boo { 
public: 
    void add() { a++; } 
    int a; 
}; 


vector<Boo> v; 
Boo b; 
b.a = 1; 
for (int i=0; i<5; i++) { 
    v.push_back(b); 
} 
v[0].add(); 
v.at(1).add(); 
Boo & refB = v[2]; refB.add(); 
refB = v.at(3); refB.add(); 
Boo & refB2 = v.at(4); refB2.add(); 
printf("%d %d %d %d %d\n", v[0].a, v[1].a, v[2].a, v[3].a, v[4].a); 

결과 :

2 2 2 1 2 

그래서 컴파일러 취급 :

Boo & refB = v[2]; refB.add(); 
refB = v.at(3); refB.add(); 
다르게

:

Boo & refB2 = v.at(4); refB2.add(); 

하지만 원래의 문제를 얻지 않는다 (즉 , v.at(n).add()은 복사하지 않고 b를 전달합니다. y 참조). 다음 라인이 복사 중입니까?

myVector.at(index).add(z1) 

컴파일러에 따라 다를 수 있습니까? 어떤 컴파일러/OS를 사용하고 있습니까?

+0

'std :: vector <>. at()'는 참조를 반환합니다. 그리고'Boo & ref = v.at (2);'는'ref []를 초기화하여'v [2]'를 참조합니다.영원히 참고 문헌을 다시 설치할 수는 없습니다. 그래서'ref = v.at (3);'v [3]를'v [2] '에 할당합니다. (일반적으로 로컬 스코프가있는 심볼을 참조로 정의하는 것은 매우 드뭅니다.) –

+0

aha! 이는 v [3]가 여전히 1 인 이유를 설명합니다. 참조를 다시 고정하면 모호한 의미로 이어질 수 있기 때문에 의미가 있습니다. – RunHolt

+0

참조를 다시 장착 할 수 있으면 포인터가됩니다. –

0

복사 생성자가 없거나 operator = overloaded 클래스가 있습니다.

이것은 별 문제가되지 않습니다.명시 적으로 사용하지 않도록 설정하지 않으면 (C++ 03에서는 구현하지 않고 private로 선언하지 않고 C++ 11에서 delete으로 정의) 컴파일러에서 생성합니다.

이제 개체 복제를 비활성화하면 더 이상 벡터에 직접 저장할 수 없으므로 벡터는 복사본을 내부적으로 복사합니다. 반면에 컨테이너에 (스마트 한) 포인터를 저장할 수는 있지만 실제로 문제를 복잡하게 만들 수 있습니다.

+0

참고 : 그가 5 가지 정도의 "특별한"방법 ​​(기본 생성자, 복사/이동 생성자, 복사/이동 할당) 중 하나만 쓰는 경우 컴파일러는 다른 옵션을 자동으로 정의하지 않습니다. – bstamour

+0

@bstamour : 어디에서 가져 왔니? 나는 그것이 옳지 않다고 확신한다.'struct test {test() {} test (test const &) {}}; int main() {테스트 a; 시험 b (a); b = a; }'잘 컴파일되고 * 암시 적으로 정의 된 * 대입 연산자를 사용합니다. –

+0

나는 표준의 어딘가에서 그것을 읽었다 고 맹세 할 수 있었다. 나는 그것을 바로 지금 발견 할 수 없다. 그래서 나는 내가 그것을 보았던 곳을 찾을 수있을 때까지 나는 실수를했다고 가정한다 :-) – bstamour

0

복사 생성자가 없거나 operator = overloaded 클래스가 있습니다.

이 경우 컴파일러가 제공합니다. 은 C++ 2003 표준 조항 12.8 인용 : 클래스 정의가 명시 적으로 복사 생성자를 선언하지 않는 경우

을, 하나는 암시 적으로를 선언된다. ... 클래스 X에 대한 내재적으로 선언 된 복사 생성자는 X::X(const X&) [또는] X::X(X&)의 형식을 갖습니다. ... 클래스 X에 대한 내재적으로 정의 된 복사 생성자는 해당 하위 객체의 구성원 단위 복사본을 수행합니다.

클래스 정의가 명시 적으로 복사 할당 연산자를 선언하지 않는 경우

은, 하나는 암시 적으로
선언된다. ... 클래스 X에 대한 암시 적으로 선언 된 복사 할당 연산자는 X& X::operator=(const X&) [또는] X& X::operator=(X&)의 형식을 갖습니다. ... 클래스 X에 대한 암시 적으로 정의 된 복사 할당 연산자는 해당 하위 객체의 구성원 단위 할당을 수행합니다.