"C ++ 입문서"읽기 노트-03 장 순차 컨테이너 작업

저자 : Ma Zhifeng
링크 : https : //zhuanlan.zhihu.com/p/24432568
출처 :
저자가 거의 저작권을 가지고 있음을 알고 있습니다. 상업적 재판의 경우 저자에게 연락하여 승인을 받으십시오. 비상업적 재판의 경우 출처를 표시하십시오.

성명서:

  • 기사의 내용은 "C ++ Primer Chinese Edition (5th Edition)"에서 수집 및 편집되었으며 저작권은 원서에 있습니다.
  • 원본 책은 더 자세하고 멋진 해석을 가지고 있으므로 학습용 정품 책을 구입하세요.
  • 이 기사는 학습과 의사 소통을위한 것이며 어떠한 형태의 전재도 금지되어 있습니다.

본문

  1. 요소 추가
  2. 액세스 요소
  3. 요소 삭제
  4. 컨테이너 크기 변경
  5. 다른

순차 컨테이너에 요소 추가

  • 푸시
    • push_back
    • push_front
  • 끼워 넣다
  • 나는 좋아한다

벡터, 문자열 또는 deque에 요소를 삽입하면 컨테이너에 대한 모든 반복기, 참조 및 포인터가 무효화 될 수 있습니다. 요소를 추가하면 전체 객체 공간이 재 할당 될 수 있기 때문입니다 (새 요소가 삽입 된 후 이전 공간은 객체를 수용하기에 충분하지 않습니다). 객체의 저장 공간을 재 할당하려면 새 메모리를 할당하고 요소를 이전 공간에서 새 공간으로 이동해야합니다.

저자는 다음과 같이 말합니다.

추가 및 삭제와 같은 컨테이너 작업을 사용할 때 먼저 요소 공간의 컨테이너 할당 전략을 고려하십시오.

push_back

컨테이너 끝에 요소 추가

array 및 forward_list를 제외하고 모든 순차 컨테이너가 지원됩니다. (기억할 필요 없음, 요소 공간의 컨테이너 할당 전략 고려)

container.push_back(word);

저자는 다음과 같이 말합니다.

객체로 컨테이너를 초기화하거나 컨테이너에 객체를 삽입 할 때 실제로 객체 자체가 아닌 객체 값의 복사본을 넣습니다. 객체에 대한 참조도 아니며 둘 사이에 연결도 없습니다.

push_front

컨테이너 헤드에 요소 삽입

목록, forward_list 및 deque 만 지원 (기억할 필요 없음, 요소 공간의 컨테이너 할당 전략 고려)

for(size_t ix = 0; ix != 4; ++ix )
{
    ilist.push_front(ix);
}

각 요소는 컨테이너의 헤드에 삽입되어 결국 역순을 형성합니다.
Leetcode 정수 역순을 다시 작성하는 등이 기능을 활용할 수 있습니까?

끼워 넣다

임의의 위치에 0 개 이상의 요소 삽입

vector, deque, list 및 string은 모두
특수 버전의 insert를 사용하여 forward_list를 지원 합니다.

삽입에는 여러 오버로드 된 함수가 있습니다.

  • insert (itr, t) itr이 가리키는 위치 앞에 t를 삽입합니다.
  • insert (itr, n, t) itr이 가리키는 위치 앞에 n t 삽입
  • insert (itr, itr1, itr2)는 itr이 가리키는 위치 앞에 (itr1, itr2) 범위의 요소를 삽입합니다.
  • insert (itr, il) itr이 가리키는 위치 앞에 {} 목록을 삽입합니다.

유사성:

  1. 첫 번째 매개 변수는 삽입 위치를 지정하는 데 사용되는 반복기입니다.
  2. 주어진 반복자가 가리키는 위치 앞에 요소를 삽입하십시오.
  3. 추가 된 첫 번째 요소에 대한 반복기를 반환합니다.

삽입 함수에는 push_back 및 push_front의 기능도 있습니다.

list.insert(list.begin(), 1);
list.insert(list.end(), 1);

첫 번째 요소 앞에 삽입합니다. 즉, push_front가
마지막 요소, 즉 push_back 앞에 삽입됩니다.

삽입 함수의 반환 값 사용

list<string> lst;
auto iter = lst.begin();
while( cin >> word )
{
    iter = lst.insert( iter, word );
}

항상 push_front를 호출하는 것과 같습니다.

Emplace

새로운 표준 도입

미리 만들어진 객체를 밀어 넣고 삽입하고,
emplace는 객체를 생성하여 컨테이너에 삽입하므로
해당 매개 변수는 컨테이너 요소 유형 생성자의 매개 변수와 동일합니다.

struct Sales_data{
    Sales_data(const string &s, unsigned n, double p);
};

list<Sales_data> c;
c.emplace("934", 25, 1.2);

emplace를 사용하면이 차이를 기억하기 만하면되고 다른 것들은 비유로 사용할 수 있습니다.

push_front----emplace_front
push_back----implace_back
insert-----implace

액세스 요소

  • 아래 첨자
  • ...에서

반환 값은 해당 위치 요소에 대한 참조입니다.

컨테이너의 시작과 끝에서 요소를 가져 오려면 다음을 수행 할 수 있습니다.

auto val1 = *c.begin();
auto last = c.end();
auto val2 = *(--last);

더 간단한 방법은 앞뒤를 사용하는 것입니다.

auto val1 = c.front();
auto val2 = c.back();

사용하기 전에 용기가 비어 있는지 확인해야합니다.

아래 첨자와 비교할 때 아래 첨자가 범위를 벗어난 경우 at will out_of_range 예외가 발생합니다.

요소 삭제

    • pop_back
    • pop_front
  • 삭제
  • 맑은

삽입 된 작업과 비교하여 이해할 수 있습니다.

  • 지우기 (itr)
  • 지우기 (itr1, itr2)

erase의 반환 값은 마지막으로 삭제 된 요소 뒤를 가리키는 반복자이기도합니다.

전형적인 예, List에서 모든 홀수 요소 삭제

list<int> lst = {0,1,2,3,4,5,6,7,8,9};
auto it = lst.begin();
while( it != lst.end() )
{
    if( *it % 2 )
    {
        it = lst.erase(it);
    }
    else
    {
        ++it;
    }
}

forward_list 작업

앞서 언급했듯이 먼저 요소 공간을 할당하는 컨테이너의 전략을 고려하십시오. forward_list는 할당 전략이 다르기 때문에 지원하기 위해 특별한 작업이 필요합니다.

ele1-->ele2-->ele3-->ele4  
ele1-->ele2--------->ele4

요소 값을 저장하는 것 외에도 각 요소는 다음 요소의 주소도 저장합니다.
따라서 ele3를 삭제하려면 ele2의 후속 작업을 수정해야하며 ele2에서 ele3까지 가져올 방법이 없습니다.

forward_list에서 요소를 추가하거나 삭제하는 작업은 지정된 요소 뒤에있는 요소를 변경하여 수행됩니다.

insert_after(p,t)
insert_after(p,n,t)
insert_after(p,b,e)
insert_after(p, il)
erase_after(p)
erase_after(b,e)
implace_after(p,args)

마찬가지로 마지막 반복자는 forward_list에 대해 의미가 없으므로 첫 번째 반복자가 추가됩니다.

before_begin()

컨테이너 크기 변경

c.resize(n, t)

컨테이너가 축소되면 컨테이너 뒷면의 요소가 삭제
되고 컨테이너가 확대되면 t를 사용하여 새로 추가 된 요소를 초기화합니다.

t는 선택 사항입니다.

반복자 실패

앞서 언급했듯이 요소를 추가하거나 삭제하면 반복기가 실패 할 수 있습니다.

컨테이너의 작동을 변경 한 후 반복자의 위치를 ​​변경하는 것이 좋습니다.

vector<int> vi = {0,1,2,3,4,5,6,7,8,9};
auto itr = vi.begin();

while( itr != vi.end() )
{
    if( *itr % 2 )
    {
        itr = vi.insert( itr, *itr );
        itr += 2;
    }
    else
    {
        itr = vi.erase( itr );
    }
}

여기에서 삽입 및 지우기의 반환 값을 사용하여 반복자의 위치를 ​​변경합니다.

그리고 루프 조건에서는 미리 가져 오는 대신 vi.end ()가 사용됩니다.

auto end = vi.end();
wihle( begin != end ){}

작업 추가 및 삭제 후 종료도 변경되므로 즉시 획득해야합니다.

  1. 반환 값을 사용하여 반복기 위치 변경
  2. 즉시 종료하고 최종 가치를 캐시하지 마십시오.

추천

출처blog.csdn.net/qq_26751117/article/details/53730436