벡터가 커질 때 이동 의미론을 적용하는 방법은 무엇입니까?
나는이 std::vector
특정 클래스의 객체를 A
. 클래스는 사소하지 않으며 복사 생성자 와 이동 생성자가 정의되어 있습니다.
std::vector<A> myvec;
벡터를 A
객체로 채우면 (예 :) 벡터의 요소의 새 복사본을 인스턴스화하기 myvec.push_back(a)
위해 복사 생성자 A( const A&)
를 사용하여 벡터의 크기가 커집니다 .
클래스의 이동 생성자가 A
대신 사용 되도록 어떻게 든 강제 할 수 있습니까 ?
std::vector
를 사용하여 이동 생성자와 소멸자가 throw하지 않는다는 것을 C ++ (특히 ) 에 알려야 합니다 noexcept
. 그런 다음 벡터가 커지면 이동 생성자가 호출됩니다.
다음은 std::vector
다음에 의해 존중되는 이동 생성자를 선언하고 구현하는 방법입니다 .
A(A && rhs) noexcept {
std::cout << "i am the move constr" <<std::endl;
... some code doing the move ...
m_value=std::move(rhs.m_value) ; // etc...
}
생성자가 아닌 경우 noexcept
, std::vector
다음 표준이 요구하는 예외 보증을 보장 할 수 없기 때문에, 그것을 사용할 수 없습니다.
표준에서 말하는 내용에 대한 자세한 내용은 C ++ Move 의미론 및 예외를 읽어보세요.
예외와 관련이있을 수 있다고 암시 한 Bo에게 감사합니다. 또한 Kerrek SB의 조언을 고려하고 emplace_back
가능하면 사용 하십시오. 그것은 수 있습니다 빠른 (하지만 종종 아니다), 그것은 명확하고 컴팩트 수 있습니다,하지만 (특히 비 명시 적으로 생성자와) 몇 가지 함정도 있습니다.
편집 , 종종 기본값은 원하는 것입니다. 이동할 수있는 모든 항목을 이동하고 나머지는 복사합니다. 명시 적으로 요청하려면 다음을 작성하십시오.
A(A && rhs) = default;
그렇게하면 가능한 경우 noexcept가 발생합니다. 기본 Move 생성자가 noexcept로 정의되어 있습니까?
이전 버전의 Visual Studio 2015 및 이전 버전에서는 이동 의미 체계를 지원하더라도이를 지원하지 않았습니다.
흥미롭게도 gcc 4.7.2의 벡터는 이동 생성자와 소멸자가 모두 인 경우에만 이동 생성자를 사용합니다 noexcept
. 간단한 예 :
struct foo {
foo() {}
foo( const foo & ) noexcept { std::cout << "copy\n"; }
foo( foo && ) noexcept { std::cout << "move\n"; }
~foo() noexcept {}
};
int main() {
std::vector< foo > v;
for ( int i = 0; i < 3; ++i ) v.emplace_back();
}
이것은 예상 된 결과를 출력합니다.
move
move
move
내가 제거 할 때, noexcept
에서 ~foo()
, 결과는 다릅니다 :
copy
copy
copy
이것도이 질문에 대한 답이라고 생각합니다 .
std::vector
재 할당시 이동 의미론을 사용 하도록 강제하는 유일한 방법 (C ++ 17 및 초기) 은 복사 생성자를 삭제하는 것 같습니다. :). 이런 식으로 컴파일 타임에 이동 생성자를 사용하거나 죽을 것입니다. :).
std::vector
재 할당시 이동 생성자를 사용해서는 안되는 규칙이 많이 있지만 어디에서 사용해야하는지 에 대한 규칙 은 없습니다 .
template<class T>
class move_only : public T{
public:
move_only(){}
move_only(const move_only&) = delete;
move_only(move_only&&) noexcept {};
~move_only() noexcept {};
using T::T;
};
or
template<class T>
struct move_only{
T value;
template<class Arg, class ...Args, typename = std::enable_if_t<
!std::is_same_v<move_only<T>&&, Arg >
&& !std::is_same_v<const move_only<T>&, Arg >
>>
move_only(Arg&& arg, Args&&... args)
:value(std::forward<Arg>(arg), std::forward<Args>(args)...)
{}
move_only(){}
move_only(const move_only&) = delete;
move_only(move_only&& other) noexcept : value(std::move(other.value)) {};
~move_only() noexcept {};
};
Your T
class must have noexcept
move constructor/assigment operator and noexcept
destructor. Otherwise you'll get compilation error.
std::vector<move_only<MyClass>> vec;
참고URL : https://stackoverflow.com/questions/8001823/how-to-enforce-move-semantics-when-a-vector-grows
'your programing' 카테고리의 다른 글
런타임에 스스로 업데이트 할 수있는 Java 애플리케이션을 어떻게 작성할 수 있습니까? (0) | 2020.10.05 |
---|---|
단어와 일치하지 않는 자바 스크립트 정규식 (0) | 2020.10.05 |
Url.Action이 내 URL에 &를 넣습니다. 어떻게 해결할 수 있습니까? (0) | 2020.10.05 |
파일 범위에서 다양하게 수정 된 배열 (0) | 2020.10.05 |
기존 디렉토리를 Eclipse 프로젝트로 만드는 방법 (0) | 2020.10.05 |