교안 108p insert, erase
안녕하세요 🙂 큰돌님
교안 108p에 있는 예제코드를 제가 insert와 erase를 이해하기 위해서 아래와 같이 변경하였는데요.
#include <bits/stdc++.h>
using namespace std;
list<int> a;
void print(list<int> a)
{
for (auto it : a)
cout << it << " ";
cout << '\n';
}
int main()
{
for (int i = 1; i <= 3; i++)
a.push_back(i); // a = 1 2 3
for (int i = 1; i <= 3; i++)
a.push_front(i); // a = 3 2 1 1 2 3
auto it = a.begin();
it++;
a.insert(it, 1000); // 3 1000 2 1 1 2 3
a.insert(it, 2000); // 3 1000 2000 2 1 1 2 3
print(a);
it = a.begin();
it++;
cout << "*it : " << *it << '\n';
a.erase(it);
print(a);
cout << "*it : " << *it << '\n';
a.pop_front();
a.pop_back();
print(a);
cout << a.front() << " : " << a.back() << '\n';
a.clear();
return 0;
}다음과 같이 변경해서 출력하면,
3 1000 2000 2 1 1 2 3
*it : 1000
3 2000 2 1 1 2 3
*it : 2
2000 2 1 1 2
2000 : 2
이렇게 나오는데, insert와 erase 메서드 모두 매개변수로 전달받은 iterator에다가 각각의 기능을 실행한 뒤 그 다음 위치(그 다음 인덱스)를 가리키도록 바꿔주는 걸까요?
제 예상으로는 출력의 두 번째 *it 이 2000으로 나올 것으로 예상했는데, 2가 나와서
a.erase(it);를 했을 때, it이 인덱스 1을 가리켜서 1000을 지우고 난 뒤, 그 다음 인덱스인 2를 가리키게 돼서 2를 가리키게 된 것으로 이해하였는데 맞을까요??
마찬가지로 위의 insert도 인덱스 1 위치에서 삽입을 한 뒤, it은 인덱스 2를 가리키게 되고, 또 insert 해서 마지막엔 it이 인덱스 3을 가리키는 로직으로 이해하였습니다!
혹시 이러한 로직이 맞다면, list만 이런 것인지 다른 자료구조의 insert도 이런지 궁금합니다!
감사합니다.
답변 1
0
안녕하세요 clain님 ㅎㅎ
a.erase(it);를 했을 때, it이 인덱스 1을 가리켜서 1000을 지우고 난 뒤, 그 다음 인덱스인 2를 가리키게 돼서 2를 가리키게 된 것으로 이해하였는데 맞을까요??
마찬가지로 위의 insert도 인덱스 1 위치에서 삽입을 한 뒤, it은 인덱스 2를 가리키게 되고, 또 insert 해서 마지막엔 it이 인덱스 3을 가리키는 로직으로 이해하였습니다!
>> 해당 코드에 주석을 달아 설명해보겠습니다. 🙂
#include <bits/stdc++.h>
using namespace std;
list<int> a;
void print(list<int> a)
{
for (auto it : a)
cout << it << " ";
cout << '\n';
}
int main()
{
for (int i = 1; i <= 3; i++)
a.push_back(i); // a = 1 2 3
for (int i = 1; i <= 3; i++)
a.push_front(i); // a = 3 2 1 1 2 3
// 리스트의 시작 부분에서 두 번째 위치를 가리키는 반복자를 생성합니다.
auto it = a.begin();
it++;
// 반복자가 가리키는 위치에 1000을 삽입합니다. 리스트의 상태: 3 1000 2 1 1 2 3
a.insert(it, 1000);
// 같은 위치에 2000을 삽입합니다. 리스트의 상태: 3 1000 2000 2 1 1 2 3
a.insert(it, 2000);
print(a);
// 리스트의 시작 부분에서 두 번째 위치를 다시 가리키는 반복자를 설정합니다.
it = a.begin();
it++;
cout << "*it : " << *it << '\n'; // 반복자가 가리키는 원소(1000)를 출력합니다.
a.erase(it); // 반복자가 가리키는 원소(1000)를 삭제합니다.
print(a); // 리스트의 현재 상태를 출력합니다.
// 주의: erase 호출 후 it는 무효화되므로, 여기서 *it를 사용하면 정의되지 않은 동작을 초래합니다.
cout << "*it : " << *it << '\n'; // 이 코드는 UB를 초래합니다.
a.pop_front(); // 리스트의 첫 번째 원소를 삭제합니다.
a.pop_back(); // 리스트의 마지막 원소를 삭제합니다.
print(a); // 리스트의 현재 상태를 출력합니다.
// 리스트의 첫 번째와 마지막 원소를 출력합니다.
cout << a.front() << " : " << a.back() << '\n';
a.clear(); // 리스트의 모든 원소를 삭제합니다.
return 0;
}
저의 경우 이 코드를 실행했더니 2가 아니라 1000이 뜹니다.
3 1000 2000 2 1 1 2 3
*it : 1000
3 2000 2 1 1 2 3
*it : 1000
2000 2 1 1 2
2000 : 2그 이유는 이 코드에서 UB가 발생하는 부분이 있기 때문입니다.
erase 함수를 호출할 때의 it 이후 해당 반복자 it는 더 이상 유효하지 않습니다. 해당 it에 대한 부분을 지웠는데 다시 해당 부분의 값을 출력하게 되면 정의되지 않은 동작(Undefined Behavior)이 발생할 수 있습니다.
혹시 이러한 로직이 맞다면, list만 이런 것인지 다른 자료구조의 insert도 이런지 궁금합니다!
>> 네 insert가 허용되는 자료구조의 경우 보통 이런 꼴을 띄게 됩니다.
vector의 경우
vector<int> v = {1, 2, 4, 5};
// 인덱스 2에 3 삽입
v.insert(v.begin() + 2, 3);
데큐
deque<int> d = {1, 2, 4, 5};
d.insert(d.begin() + 2, 3); // 인덱스 2에 3 삽입
set
set<int> s = {1, 2, 4, 5};
s.insert(3); // 3 삽입
map
map<int, string> m = {{1, "one"}, {2, "two"}, {4, "four"}};
m.insert({3, "three"}); // 키 3에 "three" 삽입또 질문 있으시면 언제든지 질문 부탁드립니다.
좋은 수강평과 별점 5점은 제게 큰 힘이 됩니다. :)
감사합니다.
강사 큰돌 올림.
코딩살구클럽 가입부탁드립니다
0
16
2
코딩살구클럽 가입 요청 확인부탁드립니다
0
21
2
5-S 테스트 케이스 질문
0
30
2
코살 문제풀이 환경
0
45
2
2 - T 오큰수 문제가 있는 것 같습니다.
0
41
1
추천 추가문제들
0
41
2
프로그래머스 코테 환경 관련해서 질문드립니다.
0
42
2
해당 문제에 대한 채점이 코딩살구클럽에서 올바르게 처리되지 않습니다.
0
39
2
균형 이진 트리 설명 시 높이 숫자
0
30
2
4-H 질문드립니다.
0
35
2
1-K 질문드립니다.
0
41
2
대기업 인적성 시험 질문
0
41
2
4-C 질문드립니다
0
41
2
[수학숙제 / BOJ 2870] 채점 서버 오작동
0
37
1
코테 준비 질문
0
50
1
살구클럽가입 요청드려요
0
38
2
1-I 문제 질문
0
39
2
코딩살구클럽 가입
0
57
2
AI 코딩 도구 사용 시 학습 방법 조언
0
51
2
코딩살구클럽 오류
0
61
2
코살클 [3-F 괄호 추가하기] 프라이빗 9번 제보
0
46
1
코딩살구클럽 테스트 케이스 오류 제보
0
52
2
삼성 코딩테스트
0
61
2
틀린 이유를 못찾겠습니다
0
47
2





