C ++에는 매개 변수를 함수에 전달하는 세 가지 방법이 있습니다 : 값, lvalue 참조 및 rvalue 참조. 이 중에서 값을 전달하면 호출 된 함수가 자체 사본을 수신한다는 의미에서 소유권을 생성하고 rvalue 참조를 전달하면 값이 소비 될 수 있음을 나타냅니다. 즉, 더 이상 호출자가 사용하지 않습니다. lvalue 참조로 전달하면 오브젝트가 호출자로부터 일시적으로 차용되었음을 의미합니다.
그러나 이러한 규칙은 "규칙에 따른"경향이 있으며 컴파일러가 항상 확인할 수는 없습니다. 그리고 실수로을 사용하여 lvalue 참조를 rvalue 참조로 바꿀 수 있습니다 std::move()
. 구체적으로 세 가지 문제가 있습니다.
참조는 참조하는 객체보다 오래 지속될 수 있습니다. 녹의 평생 시스템은 이것을 방지합니다.
언제든지 하나 이상의 변경 가능 / 비 Const 기준이 활성화 될 수 있습니다. Rust의 빌림 검사기는 이것을 방지합니다.
참조를 선택 해제 할 수 없습니다. 호출 된 함수의 서명을 모르면 해당 함수가 객체에 대한 참조를 생성하는지 여부를 콜 사이트에서 확인할 수 없습니다. 따라서 클래스의 특수 메소드를 삭제하거나 일부 "참조 없음"스타일 안내서를 준수하는지 콜 사이트를 감사하여 참조를 확실하게 막을 수 없습니다.
수명 문제는 기본 메모리 안전에 관한 것입니다. 물론 참조 된 객체가 만료되었을 때 참조를 사용하는 것은 불법입니다. 그러나 객체 내에 참조를 저장할 때, 특히 해당 객체가 현재 범위보다 오래 지속되는 수명을 잊어 버리는 것은 매우 쉽습니다. C ++ 타입 시스템은 객체 수명을 전혀 모델링하지 않기 때문에 이것을 설명 할 수 없습니다.
std::weak_ptr
스마트 포인터는 일반 기준과 유사한 인코딩 소유권 의미를 수행하지만, 참조 된 개체가를 통해 관리 될 것을 요구 shared_ptr
, 즉 참조 카운트입니다. 이것은 비용이 들지 않는 추상화가 아닙니다.
C ++에는 const 시스템이 있지만 객체를 수정할 수 있는지 여부는 추적하지 않지만 해당 특정 참조를 통해 객체를 수정할 수 있는지 여부를 추적합니다 . "무서 한 동시성"에 대한 충분한 보장을 제공하지 않습니다. 반대로 Rust는 유일한 참조 인 (“이 오브젝트를 변경할 수있는 유일한 사람입니다”) 활성 변경 가능한 참조가 있고 변경 불가능한 참조가있는 경우 해당 오브젝트에 대한 모든 참조는 변경할 수 없습니다 ( "객체에서 읽을 수는 있지만 아무도 변경할 수 없습니다").
C ++에서는 뮤텍스가있는 스마트 포인터를 통해 객체에 대한 액세스를 보호하려는 유혹을받을 수 있습니다. 그러나 위에서 언급했듯이 참조가 있으면 예상 수명을 벗어날 수 있습니다. 따라서 이러한 스마트 포인터는 관리 대상 개체에 대한 단일 액세스 지점임을 보장 할 수 없습니다. 이러한 계획은 실제로 대부분의 프로그래머가 스스로 방해하기를 원하지 않기 때문에 실제로 작동 할 수 있지만 유형 시스템 관점에서 볼 때 이것은 여전히 완전하지 않습니다.
스마트 포인터의 일반적인 문제점은 핵심 언어 위에있는 라이브러리라는 것입니다. 핵심 언어 기능 세트는 이러한 스마트 포인터를 가능하게합니다 (예 : std::unique_ptr
이동 생성자 필요). 그러나 핵심 언어 내에서 결함을 수정할 수는 없습니다. 함수를 호출 할 때 암시 적으로 참조를 작성하고 함께 참조를 매달려있는 기능은 핵심 C ++ 언어가 적절하지 않다는 것을 의미합니다. 변경 가능한 참조를 단일 참조로 제한 할 수 없다는 것은 C ++이 모든 종류의 동시성으로 경쟁 조건에 대한 안전을 보장 할 수 없음을 의미합니다.
물론 많은 측면에서, C ++과 Rust는 특히 정적으로 결정된 객체 수명 개념에 대해 싫어하는 것보다 더 비슷합니다. 그 동안 그러나 수 (프로그래머의 제공 아무도 실수를하지 않습니다) 올바른 C ++ 프로그램을 작성, 녹 보장 논의 된 속성에 대한 정확성.