리소스를 보유하는 클래스를 작성할 때 간단한 스왑 함수를 작성하여 리소스를 전송/복사하는 프로세스를 단순화하는 데 익숙합니다. ,언제 교환 기능이 필요합니까?
class MyArray {
public:
MyArray(size_t size) :
_array(size)
{
}
int & operator[](size_t size) {
if(index >= size()) throw std::exception("Index Out of Bounds!");
return _array[index];
}
const int & operator[](size_t index) const {
if(index >= size()) throw std::exception("Index Out of Bounds!");
return _array[index];
}
size_t size() const {
return _array.size();
}
private:
std::vector<int> _array;
};
그리고 두 번째 코드에 swap
기능 기본값 : 내가 [등가]과 같이 동일한 코드를 구현하려면 선택한 수있다, 그러나
class MyArray {
public:
MyArray(size_t size) :
_array(size ? new int[size] : nullptr),
_size(size)
{
}
MyArray(const MyArray & mv) :
MyArray(mv._size)
{
if(mv._size) std::copy(mv._array, mv._array + mv._size, _array);
}
static void friend swap(MyArray & mv1, MyArray & mv2) noexcept {
std::swap(mv1._array, mv2._array);
std::swap(mv1._size, mv2._size);
}
MyArray(MyArray && mv) {
swap(*this, mv);
}
MyArray & operator=(MyArray mv) {
swap(*this, mv);
return *this;
}
~MyArray() noexcept {
delete[] _array;
}
int & operator[](size_t index) {
if(index >= _size) throw std::exception("Index Out of Bounds!");
return _array[index];
}
const int & operator[](size_t index) const {
if(index >= _size) throw std::exception("Index Out of Bounds!");
return _array[index];
}
size_t size() const {
return _size;
}
private:
int * _array;
size_t _size;
};
: 다음 코드는 사소한 예입니다 정상적인 std::swap
동작 (즉, 첫 번째 코드를 임시로 이동 구성하고 두 번째 코드를 첫 번째 코드로 이동 할당 한 다음 두 번째 코드로 임시 할당을 이동 할당합니다. 첫 번째 코드와 동일해야합니다.
그때이 문제는, 내가 명시 적으로 swap
함수를 정의해야 시나리오가 될 것입니다 무슨 이지만, 특별히 난 그냥 첫 번째 예제 코드에서 같은 코드를 (재사용하기 위해 노력하고있어 시나리오 아니다)? 코드에서 명시 적으로 리소스를 관리하는 것이 없지만 swap
함수의 이점을 객관적으로 얻을 수있는 명백한 시나리오가 있습니까? 필자가 작성한 모든 [move-constructable] 클래스에 대해 swap
함수를 자동 쓰기해야하나요, 아니면 그냥 그렇게하면 코드를 낭비할까요?
auto tmp = std::move(rhs);
rhs = std::move(lhs);
lhs = std::move(tmp);
이 발생하는 3 개 움직임을 유발하고, 존재하는 경쟁 임시 개체가 필요합니다 : 당신이 당신의 자신의 스왑 작업을 정의하지 않으면
스왑과 관련하여 이동 생성자를 정의 할 필요는 없습니다. 사실, const 필드의 경우에도 이것은 불가능합니다. 자신 만의 글을 쓸 수도 있습니다. – lorro
@lorro 코드를 더 간단하게 만들었 기 때문에 * to *를 선택했다는 것을 암시한다고 생각하지 않습니다. – Xirema
'MyArray (MyArray && mv)'는 멤버를'mv'로 바꾸기 전에 멤버를 초기화하지 않으므로'mv'가 유효하지 않은 상태로 남겨져 이동 의미를 위반하게됩니다. 먼저 유효한 공백 상태로 초기화 한 다음 스왑하므로'mv'는 공백 상태로 설정됩니다. 예를 들면 다음과 같습니다 :'MyArray (MyArray && mv) : MyArray (0) {swap (* this, mv); }' –