와우, 천천히!
당신은 당신의 기억으로 꽤 미친 짓을하고 있습니다. 그래서 처음부터 시작합시다.
3 개의 요소가있는 단일 벡터가 있습니다. 포인터를 사용하여 벡터를 참조하려고합니다. 어떻게 보이는지 보자.
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
// No no no no! You don't have to `new` a pointer that
// you're going to assign to something else!
// This is called a memory leak, and it means you've just wasted (!!!)
// C++ memory! Don't do it
// vector<double>* new_mv_pt = new vector<double> (3);
// Instead, do this:
vector<double>* ptr_to_mv = &mv; // No leak, immediately points to a vector<double> mv;
첫 번째 비트는 처리된다. 이제 좀 더 깊숙이 들어가 봅시다. 벡터에 대한 참조 벡터를 저장하려고합니다. 좋아, 그건 공평 해. 그것에 대해 갈 수있는 몇 가지 방법이 있습니다.의는 mv
의 예와 다른 것들로 돌아 가자 : 코드에서이 시점에서
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
vector<double>* ptr_to_mv = &mv;
// So far so good. Now, based on your question, you want
// to have a list of these to point to. So:
vector<vector<double>*> vop;
vop.push_back(ptr_to_mv); // All clean.
, 당신은 당신이 역 참조 *
또는 사용과 더불어, vector<double>*
에 도착 .at()
또는 operator[]
와 vop
에 액세스 할 수 있습니다 ->
는 직접 작업하기 :이 모든 당신이 mv
를 참조하기 때문에
가
std::vector<double>* ptr_to_vector = vop[0]; // Got my pointer
std::cout << ptr_to_vector->at(0) << std::endl; // Prints '233'
이 (233)를 인쇄합니다. 다른 대답의 주석에서 이러한 포인터를 삭제하면 어설 션이 발생한다고 말했습니까? 두 번 삭제하면되기 때문에 발생합니다.
오래 전에 신고 한 mv
을 기억하십니까? 글쎄, 당신은 역동적 인 벡터로 만들지 않았어. 너는 new
이 아니고 포인터가 아니야. 따라서 함수가 종료되면 자동으로 자신을 삭제합니다. 소멸자를 호출하고 이 스택에서 죽습니다.. ptr_to_vector
또는 ptr_to_mv
은 모두 mv
을 참조하며, 자체적으로 정리됩니다.
당신이 그것에 삭제 호출하면 , 당신은 mv
에 삭제 호출하려는 당신이 더블 삭제하는 (즉, 당신이 가리키고 기능)!
따라서 mv
에 대한 포인터가 있으면 삭제하지 마십시오. 스택 기반 변수입니다. 그것은 스스로 청소할 것입니다.
여전히 다음과 같습니까? 좋아, 이제 그것으로 얻을 좀 더하자 : 이제
를, 내가 전에 말한대로 (벡터, 당신은 오래된 포인터를 우선 할당하지를 new
필요이유가있는 경우, 당신은 기억을 떠날거야). 그냥 있기 때문에 우리가 모두하지 않는 또 다른 하나는, 삭제 호출하여 정리 될 필요가 vop
, 내부와 2 포인터를 가지고 :
// Our vector of double vector pointers
vector<vector<double>*> vop;
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
// References a stack variable: don't delete
vector<double>* ptr_to_mv = &mv;
vop.push_back(ptr_to_mv);
// Makes a fresh copy of mv. You must delete this
// manually
vector<double>* fresh_ptr = new vector<double>(mv);
(*fresh_ptr)[0] = 1337;
// changes only data in fresh_ptr, not `mv`
vop.push_back(fresh_ptr);
/* Blah blah blah, work */
// Functions about to exit, gotta clean up!
delete fresh_ptr;
//delete ptr_to_mv; // NO.
//delete vop[0]; // NO!
//delete vop[1]; // ... Already deleted from fresh_ptr
// ... This is going to get tedious if we don't have a fresh_ptr
// for every vector we need!
위 문제를 보여줍니다 : 당신은 완전히 신선한 새로운 포인터를 만들 자동으로 청소하는 mv
에 대한 참조! 벡터를 반복하고 모든 것을 삭제하면 그 불쾌한 주장이 일어납니다. 우리는 그것을 어떻게 다루고 우리가 필요로하는 깨끗한 것을 얻습니까?
지저분한 빠른 해결책 1은 단지 delete vop[1]
/fresh_ptr
이고 끝내야합니다. 더 나은 해결책은 리소스가 올라갈 때마다 new
이 std::unique_ptr
이라는 훌륭한 멋진 내용으로 마무리된다는 것입니다. 코드는 다음과 같을 것입니다 :
그리고 거기에있는 모든 주석 처리 된 코드를 제거하면 갑자기 물건이 청결합니다!
물론, 지금, 내가 당신을 위해 가지고있는 마지막 질문은 다음과 같습니다 은 도대체 당신이 그 일을하는 것은 벡터의 포인터의 참조 포인터에 모든 포인터를 필요로?
먼저 답을 얻으십시오. 둘째, 처음에는 메모리 사용 지점의 절반 이상을 차지하는 벡터의 메모리 관리 기능을 제거했기 때문에 이것이 끔찍한 아이디어라는 것을 알아 두십시오. –
저는 왜 그가 처음에 벡터에 대한 포인터를 가지고 있는지 알아 내려고합니다. 이것은 같은 기능/클래스에있는 경우 특히 이렇게하는 것은 개념적으로 의미가 없습니다. –