std :: begin 및 std :: end가 "메모리 안전하지 않은"이유는 무엇입니까?
에서 이 블로그 게시물 , 에릭 Niebler는 말한다 :
std :: begin 및 std :: end의 문제점은 무엇입니까? 놀라다! 메모리 안전하지 않습니다. 이 코드의 기능을 고려하십시오.
extern std::vector<int> get_data(); auto it = std::begin(get_data()); int i = *it; // BOOM
std :: begin에는 const 및 non-const lvalue에 대해 두 개의 오버로드가 있습니다. 문제는 rvalue가 const lvalue 참조에 바인딩되어 위의 dangling iterator로 이어진다는 것입니다.
나는 그의 요점을 이해하는 데 어려움이 있으며 왜 it
매달린 참조가 있습니다. 누군가 설명 할 수 있습니까?
이 get_data
함수는 객체를 반환합니다. 표시된 방식으로 사용하면 해당 객체는 임시 객체가되며 전체 표현식이 종료되면 삭제됩니다. 이터레이터는 이제 더 이상 존재하지 않는 벡터 객체를 참조하며 역 참조하거나 유용한 방법으로 사용할 수 없습니다.
Eric의 요점은 시작하는 인수로 rvalue 컨테이너를 std::begin
조용히 받아들이 는 것입니다. 표면적으로는 코드 문제도 다음과 같이 예시됩니다.
auto it = get_data().begin();
그러나 std::begin
무료 함수 템플릿이므로 각 컨테이너의 begin
멤버에 적절한 참조 한정자를 추가 할 필요없이 rvalue를 거부하도록 만들 수 있습니다 . "단지"포워딩으로 코드에 메모리 안전 계층을 추가 할 기회를 놓치게됩니다.
이상적으로, 과부하 세트 는
template< class C >
void begin( C&& ) = delete;
이로 인해 블로그 게시물의 코드가 그 자리에서 거부되었을 것입니다.
에서 반환 된 임시 벡터 는 완료된 get_data
후 범위를 벗어 std::begin
납니다. 살아있는 상태로 유지되지 않으므로 it
파괴 된 객체에 대한 반복자도 마찬가지 입니다.
이것이 std :: begin의 메모리 안전 실패라고 말하는 것이 공평합니까? 컨테이너가 삭제 된 후 포인터를 따라가는 것이 유효하도록 반복기를 만드는 '안전한'방법은 없습니다.
다른 메서드에 대한 검사는 없지만 범위 파생 반복기를 팝업으로 만들 수있는 방법이없는 것과는 다릅니다. 좀 더 노력하면 돼 ...
rvalue에서 초기화를 허용하기 때문에 좋지 않습니다.
사실, 복잡한 기능은 다음과 같은 두 가지 짧은 기능으로 단순화 할 수 있습니다.
int& foo(int x){
return x;
}
int generate_a_int(){
return 42;
}
그런 다음 그것을 호출하면 foo(generate_a_int())
임시 값이 생성되고 함수 본문에서 일단 생성 된 임시 값 generate_a_int()
이 파괴되고 매달린 참조가 발생합니다.
이제 이해가 되나요?
참조 URL : https://stackoverflow.com/questions/54625792/why-are-stdbegin-and-stdend-not-memory-safe
'IT Share you' 카테고리의 다른 글
CertPathValidatorException : 인증서 경로에 대한 신뢰 앵커를 찾을 수 없음-Retrofit Android (0) | 2021.01.10 |
---|---|
Swift에서 증가 된 값으로 배열을 만드는 방법은 무엇입니까? (0) | 2021.01.10 |
JPA / EJB3 지속성 컨텍스트에서 엔티티 분리 (0) | 2021.01.10 |
파이썬에서이 튜플을 조인 할 수없는 이유는 무엇입니까? (0) | 2021.01.10 |
iTextSharp 세트 문서 가로 (가로) A4 (0) | 2021.01.10 |