태그 보관물: rvalue-reference

rvalue-reference

const에 대한 rvalue 참조가 사용됩니까? 확인하고 싶습니다. 클래스 유형은 const

아닐 것 같지만 확인하고 싶습니다. 클래스 유형은 const Foo&&어디에 사용 Foo됩니까?



답변

때때로 유용합니다. 초안 C ++ 0x 자체는 다음과 같이 몇 군데에서이를 사용합니다.

template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;

위의 두 오버로드는 다른 ref(T&)cref(const T&)함수가 rvalue에 바인딩되지 않도록합니다 (그렇지 않으면 가능함).

최신 정보

아쉽게도 공개적으로 사용할 수없는 공식 표준 N3290을 확인 했으며 20.8 Function 객체 [function.objects] / p2에 있습니다.

template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;

그런 다음 공개적으로 사용 가능한 최신 C ++ 11 이후 초안 인 N3485 를 확인했으며 20.8 함수 개체 [function.objects] / p2에서 여전히 다음과 같이 말합니다.

template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;


답변

const rvalue 참조 (for가 =delete아님) 를 얻는 의미는 다음과 같은 의미입니다 .

  • lvalue에 대한 연산을 지원하지 않습니다!
  • 비록, 우리는 여전히 복사 우리가 할 수 없기 때문에, 이동 전달 된 자원을, 또는 실제 의미가 없기 때문에 그것을 “이동”.

다음 사용 사례 수 있었다 이럴위한 좋은 사용 사례 를 const를 rvalue 참조 언어가이 방법을 (참조 걸릴하지 않기로 결정하지만, 원래의 SO 게시물을 ).


사례 : 원시 포인터의 스마트 포인터 생성자

일반적으로 사용하는 것이 좋습니다 것 make_unique하고 make_shared있지만, 모두 unique_ptrshared_ptr원시 포인터로 구성 될 수있다. 두 생성자 모두 값으로 포인터를 가져 와서 복사합니다. 둘 다 생성자에서 전달 된 원래 포인터의 연속 사용을 허용합니다 (예 : 방지하지 마십시오 ).

다음 코드는 double free로 컴파일되고 결과를 얻습니다 .

int* ptr = new int(9);
std::unique_ptr<int> p { ptr };
// we forgot that ptr is already being managed
delete ptr;

모두 unique_ptrshared_ptr그 관련 생성자가 원시 포인터를 얻을 것으로 예상한다면 위를 방지 할 수 CONST를 rvalue로 에 대한 예 unique_ptr:

unique_ptr(T* const&& p) : ptr{p} {}

이 경우 위 의 이중 자유 코드는 컴파일되지 않지만 다음은 다음과 같습니다.

std::unique_ptr<int> p1 { std::move(ptr) }; // more verbose: user moves ownership
std::unique_ptr<int> p2 { new int(7) };     // ok, rvalue

참고 ptr잠재적 인 버그가 완전히 사라되지 않도록 아직도 후 사용할 수는 이동되었다. 그러나 사용자가 std::move이러한 버그 를 호출해야하는 경우 일반적인 규칙에 해당합니다. 이동 된 리소스를 사용하지 마십시오.


다음과 같이 질문 할 수 있습니다. OK,하지만 왜 T* const&& p 입니까?

그 이유는 간단 합니다. unique_ptr const pointer에서 생성을 허용하기 때문입니다 . 그 기억 CONST의를 rvalue 참조가 단지보다 제네릭 를 rvalue 참조 가 모두 허용으로 constnon-const. 따라서 다음을 허용 할 수 있습니다.

int* const ptr = new int(9);
auto p = std::unique_ptr<int> { std::move(ptr) };

rvalue 참조 (컴파일 오류 : const rvaluervalue에 바인딩 할 수 없음) 만 기대한다면이 방법은 진행되지 않습니다 .


어쨌든, 이런 제안을하기에는 너무 늦었습니다. 그러나이 아이디어는 const 에 대한 rvalue 참조 의 합리적인 사용법을 제시합니다 .


답변

그것들은 허용되고 심지어 함수는를 기준으로 순위가 매겨 const지지만에서 참조하는 const 객체에서 이동할 수 없기 const Foo&&때문에 유용하지 않습니다.


답변

std :: ref 외에도 표준 라이브러리는 동일한 목적으로 std :: as_const의 const rvalue 참조를 사용합니다 .

template <class T>
void as_const(const T&&) = delete;

래핑 된 값을 가져올 때 std :: optional 에서 반환 값으로도 사용됩니다 .

constexpr const T&& operator*() const&&;
constexpr const T&& value() const &&;

뿐만 아니라 std :: get :

template <class T, class... Types>
constexpr const T&& get(const std::variant<Types...>&& v);
template< class T, class... Types >
constexpr const T&& get(const tuple<Types...>&& t) noexcept;

이는 아마도 래핑 된 값에 액세스 할 때 래퍼의 일관성뿐 아니라 값 범주를 유지하기위한 것입니다.

이것은 const rvalue ref-qualified 함수가 래핑 된 객체에서 호출 될 수 있는지 여부에 차이를 만듭니다. 즉, const rvalue ref 한정 함수의 용도를 알지 못합니다.


답변

이것이 직접적으로 유용 할 것이라고 생각할 수는 없지만 간접적으로 사용될 수 있습니다.

template<class T>
void f(T const &x) {
  cout << "lvalue";
}
template<class T>
void f(T &&x) {
  cout << "rvalue";
}

template<class T>
void g(T &x) {
  f(T());
}

template<class T>
void h(T const &x) {
  g(x);
}

g 의 T 는 T const이므로 f ‘s x는 T const &&입니다.

이로 인해 f (객체를 이동하거나 사용하려고 할 때) 에 comile 오류가 발생할 가능성이 있지만 f 는 rvalue-ref를 가져 와서 rvalue를 수정하지 않고 lvalue에서 호출 할 수 없도록 할 수 있습니다 (너무 단순한 위의 예).


답변