벡터는 처음부터 요소의 개수를 정해 주고 생성해도 됨

vector<int> v(10);

 

string은 int 매개 변수를 받는 생성자가 없기 때문에 컴파일되지 않음

string s(10);
error C2665: 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string'
: no overloaded function could convert all the argument types

 

string은 클래스가 아니라 using 타입

C++은 임의의 문자 특성(traits)을 가진 임의의 문자 타입을 임의의 할당자를 써서 메모리에 저장한 단위의 시퀀스를 문자열이라고 봄

C++에서 쓰이는 string처럼 동작하는 모든 객체는 basic_string 템플릿을 인스턴스화한 것

따라서 컴파일러 진단 메시지에 string 대신 basic_string이 언급됨

_EXPORT_STD using string  = basic_string<char, char_traits<char>, allocator<char>>;

 

 

할당자를 받는 생성자는 웬만하면 쓰지 말자

이 생성자는 해당 컨테이너와 동일한 타입인데 동등하지 않은(inequivalent) 할당자를 가진 상태로 되기 때문에 위험

 

Effective STL 항목 11 커스텀 할당자를 제대로 사용하는 방법을 이해하자

벤치마킹/프로파일링/테스트를 통해 디폴트 STL 할당자가 별로일 수 있음 커스텀 할당자가 필요한 경우속도가 느림 메모리 효율이 낮은 경우메모리 단편화가 발생같은 종류의 객체를 특정한

eovywjr1.tistory.com

 

class NiftyEmailProgram
{
public:
	void showEmailAddress(const string& nickname) const;

private:
	using NicknameMap = map<string, string>;
	NicknameMap nicknames;
};

void NiftyEmailProgram::showEmailAddress(const string& nickname) const
{
	NicknameMap::iterator iter = nicknames.find(nickname);
	if (iter != nicknames.end())
	{

	}
}
no suitable user-defined conversion from "std::_Tree<std::_Tmap_traits<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string>>, false>>::const_iterator"
(aka "std::_Tree_const_iterator<std::_Tree_val<std::conditional_t<true, std::_Tree_simple_types<std::pair<const std::string, std::string>>, std::_Tree_iter_types<std::pair<const std::string, std::string>,
unsigned long long, long long, std::pair<const std::string, std::string> *, const std::pair<const std::string, std::string> *, std::_Tree_node<std::pair<const std::string, std::string>, void *> *>>>>")
to "std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<const std::string, std::string>>>::iterator"
(aka "std::conditional_t<false, std::_Tree_const_iterator<std::_Tree_val<std::conditional_t<true, std::_Tree_simple_types<std::pair<const std::string, std::string>>,
std::_Tree_iter_types<std::pair<const std::string, std::string>, unsigned long long, long long, std::pair<const std::string, std::string> *, const std::pair<const std::string, std::string> *, std::_Tree_node<std::pair<const std::string, std::string>, void *> *>>>>,
std::_Tree_iterator<std::_Tree_val<std::conditional_t<true, std::_Tree_simple_types<std::pair<const std::string, std::string>>, std::_Tree_iter_types<std::pair<const std::string, std::string>,
unsigned long long, long long, std::pair<const std::string, std::string> *, const std::pair<const std::string, std::string> *, std::_Tree_node<std::pair<const std::string, std::string>, void *> *>>>>>") exists

_Tree는 표준 연관 컨테이너를 구현하는 내부 템플릿

중간에 타입을 생략하고 보면 no suitable user-defined conversion from const_iterator to iterator이므로 iter를 map::find가 반환한 const_iterator로 초기화하는데 iterator로 변환하는데 실패했다는 의미

nicknames는 비상수 객체이고, find는 비상수 반복자를 반환하지만 showEmailAddress가 const 멤버 함수이므로 nicknames가 상수 객체가 되기 때문에 find가 const_iterator를 반환

따라서 iter를 const_iterator로 변경하거나 함수의 const를 제거해야 함

 

컴파일러 진단 메시지에서 긴 템플릿 이름들을 축약하는 연습을 해야 의미를 이해할 수 있음

 

STL의 컴파일러 메시지를 이해하는 힌트

vector와 string의 경우 반복자와 포인터가 똑같기 때문에 iterator를 가지고 실수했다면 컴파일러 진단 메시지는 포인터 타입을 언급할 가능성이 매우 높음

예를 들어, 소스 코드에 vector<double>::iterator가 있다면 컴파일러 메시지는 double* 라고 함

 

back_insert_iterator, front_insert_iterator, insert_iterator 등을 언급하는 메시지는 대부분 back_inserter, front_inserter, inserter를 호출할 때 실수했다는 의미

 

출력 반복자는 대입 연산자의 내부에서 출력 혹은 삽입 동작을 취하기 때문에 이런 반복자에 대해 실수했을 때에는 대입 연산자를 언급

 

STL 알고리즘의 내부가 잘못 되었다는 에러 메시지라면 알고리즘과 함께 사용한 타입에 문제가 있는 의미

예를 들면 알고리즘에 잘못된 반복자를 전달하는 상황

// 임의 접근 반복자를 요구하는 알고리즘에 양방향 반복자를 넣는 상황
list<int>::iterator iter1, iter2;
sort(iter1, iter2);

+ Recent posts

목차