13.3 교환 작업
자원의 클래스 관리를 위해, 일반적으로 스왑 함수를 정의 할 필요가 (나의 이해는 클래스 동적으로 할당 된 메모리의 데이터 멤버가 있다는 것입니다).
기본 스왑은 이것이다 :
A temp = v1;
v1=v2;
v2=temp;
코드는 임시 변수를 생성하고,이 개 과제를 사용합니다.
당신이 객체의 객체가 매우 큰 메모리에 대한 포인터가있는 경우에 대해 생각해보십시오. 이 임시 변수가 더 소비 성능입니다 만듭니다.
**이 임시 변수를 만들 수 있지만 두 개체 내에서 데이터를 교환하지 않습니다. 13.30 **으로 연습 스왑에 표시
당신이 효율성을 향상시킬 수있는이 방법은 물론, 이 최적화의 수단 필요가 없습니다 .
우리는 클래스가 스왑의 자체 버전을 정의 정의하면, 그 알고리즘은 스왑의 사용을 요구, 스왑는 우리 자신의 정의를 호출하는 우선 순위를 부여합니다.
할당 연산자를 이용하여 스왑에서
코드를 작성하기 전에, 할당 연산자는 부주의의 일부를 작성하는 것을 잊지 수있는 반면, 작업 및 소멸자 건축을 복사 완료 할 필요성을 이해할 수있다.
이 문제에 대해 걱정하지 않아도됩니다 스왑을 사용합니다. 아래 그림과 같이
우리가 변경해야 원래의 이야기가 아닌 참조 매개 변수 참조 형이된다. 함수 호출은 소멸자를 호출 한 후이 시점에서, 두 객체의 교환 후, A는 우이 기능을 호출되는 인수의 복사합니다.
그리고 *이 객체는 전에 우를 저장됩니다.
우리는 고려 여부를 알 수 없도록하는 것은 자기 지정하고 개체 포인터 유형의 데이터 멤버가이 객체 포인트를 * 해제 할 필요성을 고려한다.
유일한 단점은 비 참조 형 매개 변수를 만들 필요가있을 수 있습니다.
연습
13.29
스왑 함수에 스왑 함수 호출은 같은 기능이지만 아니기 때문에 오버로드 기능 자연 공통 함수를 호출하고, 스왑에서 차이가 없습니다
13.30
작성하기 전에 HasPtr은 테스트되지 때문에 그래서 지금 개정에 새 문자열 (에 전달 된들)을 잊지
일부 알고리즘에서 우리는 기능 요소가 호출됩니다 이동해야합니다.
class HasPtr {
friend void swap(HasPtr& obj1, HasPtr& obj2);
public:
HasPtr(const std::string& s = std::string()) :ps(new std::string(s)), i(0) {};
HasPtr(const HasPtr& hasptr) :ps(new string(*hasptr.ps)), i(hasptr.i) {
};
//列表初始化只能在构造函数中使用
HasPtr& operator=(const HasPtr& p) {
auto temp = new string(*p.ps);
delete ps;
ps = temp;
i = p.i;
return *this;
};
~HasPtr() {
delete ps;
}
string desc() {
std::ostringstream str("");
str << "ps:" << *ps << ",i:" << i;
return str.str();
}
private:
std::string *ps;
int i;
};
void swap(HasPtr& obj1, HasPtr& obj2) {
using std::swap;
swap(obj1.ps,obj2.ps);
swap(obj1.i,obj2.i);
cout << "HasPtr::swap(HasPtr& obj1, HasPtr& obj2)" << endl;
}
13.31
다음 정렬 알고리즘은 적은 수의 매개 변수로 인해 용기의 거의 하나님을 아는 해석에 따라 스왑 기능이 호출되지 정렬 사용되는 종류의 삽입은 그래서 통화 스왑 기능이있는 경우 요소를 더 빠른 정렬이 호출되지 않은이 그것은 스왑 시간을 호출;
vector<HasPtr> vec = {string("adsf"),string("sdf"),string("jocl"),string("123"),string("sdf")};
std::sort(vec.begin(), vec.end());
for (const auto& item:vec) {
cout << item.desc() << endl;
}
다음 코드 1000 개 요소 다음 함수 호출의 추가 스왑
vector<HasPtr> vec = {string("adsf"),string("sdf"),string("jocl"),string("123"),string("sdf")};
for (int i = 0; i < 1000;++i) {
vec.push_back(string("asd"));
}
std::sort(vec.begin(), vec.end());
13.32
기타 대답 : 아무 혜택이없는, 그래서 그들이 할당 동적 메모리 할당을 포함하지 않기 때문에
그러나 나는 우리가 많은 혜택을 한 후, 임시 객체에게 스왑을 작은 가격을 다시 만들 수 있지만, 혜택을 누릴 수 있다고 생각하지만, 우리가 할당 문에 스왑을 사용하는 경우, 그것은 크게 코드의 양을 줄일 수 있고, 코드가 예외 안전합니다.
예외 여기 안전, 우리가 개체를 수정할 때 얘기 예외가 발생했을 경우, 그들은 데이터가 방해되지 않도록 할 방법을 프로그래머.
내가 하나, 우리는 삭제가 일어날 쓸 수 있습니다 이해하지만 스왑 기능, 우리는이 문제를 고려하지 않는, 두 번째는 예외가 발생하지 않도록 스왑은 새로운 것이 아니다이다. 스왑 그래서 코드는 예외 안전합니다. (견적은 또한 비정상적인 보안을 무엇을 의미하는지 이해하기 위해 더 많은 연습을 필요로 이해하지 않는다)
다음 코드 예제는 다음과 같이 다시 쓸 수 :
HasPtr& operator=(const HasPtr& p) {
++*p.ref_count;
if (--*ref_count==0) {
delete ps;
delete ref_count;
}
ps = p.ps;
ref_count = p.ref_count;
i = p.i;
return *this;
};
** 이런 식으로, 당신은 코드가 크게 감소보고, 우리는 시간의 코딩에서 삭제 객체를 잊지 방지 할 수 있습니다.
P 개의 기능이 완료된 후에 실행되기 때문에, 소멸자를 호출한다. **
물론, 여기가 아닌 형식 매개 변수 참조의 형태가 정말 성능의 관점 어떠한 혜택에서 사본을 수행해야된다. 그러나 간단한 코드 재사용의 관점에서, 또는 혜택을 아
HasPtr& operator=(HasPtr p) {
swap(*this, p);
return *this;
};