Enum Type은 enum 키워드로 정의할 수 있으며 정의하고 싶은 값에 대해 심볼을 연결시킬 수 있다.
Enum은 내부적으로는 integral types으로 표시되어 Enum은 integer로 암시적 변환이 가능하며 그 반대는 성립하지 않는다.
Enum의 디폴트 값은 0부터 시작하지만, 사용자가 임의로 값을 할당할 수 있다.
Enum은 매크로 상수가 아니며, 자신이 정의된 Scope 내에서만 Visible하다.
enum OS{LINUX, WINDOWS, ANDROID};
void printOSName(OS os) {
if (os == LINUX) {
std::cout << "LINUX" << std::endl;
}
else if (os == WINDOWS) {
std::cout << "WINDOWS" << std::endl;
}
else if (os == ANDROID) {
std::cout << "ANDROID" << std::endl;
}
}
int main()
{
OS os = LINUX;
printOSName(os); // LINUX
printOSName(WINDOWS); // WINDOWS
printOSName(static_cast<OS>(2)); // ANDROID
return 0;
}
위 코드에서 Main 함수는 각 줄에서 각 Enum 값을 함수에 전달한다. 세번째 호출에서 2는 OS로 암시적 변환이 불가능하기 때문에 정적 캐스팅을 사용했다.
Enum에서 각 열거자(enumerator)들은 서로 다르게 정의된 열거형에서 중복될 수 있다. 예를 들어 enum Color의 RED와 enum Team의 RED가 중복되는 경우가 있다. 이 때 enum class를 사용해서 스코프를 사용하면 이런 충돌을 막을 수 있다.
#include <iostream>
enum class OS{LINUX, WINDOWS, ANDROID};
void printOSName(OS os) {
if (os == OS::LINUX) {
std::cout << "LINUX" << std::endl;
}
else if (os == OS::WINDOWS) {
std::cout << "WINDOWS" << std::endl;
}
else if (os == OS::ANDROID) {
std::cout << "ANDROID" << std::endl;
}
}
enum class ProjectName{SEARCH, ANDROID};
int main()
{
OS os = OS::LINUX;
printOSName(os);
printOSName(OS::WINDOWS);
printOSName(static_cast<OS>(2));
return 0;
}
다음과 같이 enum class를 사용해 Enum을 정의한 후 Name을 Scope로 사용해 심볼이 같은 Enumerator를 구별할 수 있다.
C++에서는 Raw한 문자열로 Char *를 지원한다. Char *를 사용할 때는 할당된 배열의 길이에 매우 주의해야한다. 예를 들어 Length가 10인 Char 배열은 최대 9개의 문자만을 저장할 수 있다. 문자의 끝을 Null로 구분하기 때문이다. 이 때문에 두 문자를 합친다든지 복사 한다는지의 연산에서 사용자는 항상 그 길이에 대해 신경써야하고 에러를 유발하기 쉽다.
String 클래스는 그 모든 복잡한 과정을 알아서 다 처리해준다. 초기화 및 대입에 있어서 Raw String도 사용할 수 있으며 String 객체 끼리 합치는 연산도 단순히 ‘+’ 연산자만 사용하면 된다. 문자열 길이 또한 알아서 관리하기 때문에 별도의 변수를 유저가 따로 정의할 필요도 없다.
#include <iostream>
#include <string>
using namespace std;
int main()
{
// Initialize & assign
string s = "hello";
s = "hello world";
// Access
s[0] = 'a';
cout << s[0] << endl;
// Size
cout << s.length() << endl;
// Insert & concatenate
string s1{"Hello "}, s2{"World!"};
s = s1 + s2;
cout << s << endl;
// Comparison
cout << (s1 == s2) << endl;
cout << s1.compare(s2) << endl;
// Removal
s.erase(0, 5);
cout << s << endl;
// Search
auto pos = s.find("World", 0);
if (pos != std::string::npos) {
cout << "Found" << endl;
}
return 0;
}
위와 같이 초기화 / 대입 / 인덱스를 통한 접근 / 합성 / 비교 / 삭제 / 검색 / 길이 등을 매우 쉽게 사용할 수 있다.
stringstream은 String 오브젝트를 stream화 시킬 수 있다.
<< 연산자와 >> 연산자 모두를 사용할 수 있어 stream에 string을 추가할 수도 있고 읽을 수도 있다.
>> 연산자로 stringstream에서 읽을 때는 띄워쓰기에 따라 stream 내부의 문자열이 구분된다.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
stringstream ss("abc def gae");
string word;
int count = 0;
while (ss >> word) {
++count;
}
cout << count;
return 0;
}
stringstream의 멤버 함수인 str()은 stringstream이 저장하고 있는 string 객체의 복사본을 리턴한다. istringstream과 ostringstream은 각각 읽기와 쓰기만 할 수 있다고 생각하면 된다.
C++에서는 integer, float, string 등의 여러 타입의 리터럴을 제공한다. 14.0f나 322L 또는 L”hello”와 같은 것들이 그 예다. C++11에서 부터는 사용자도 리터럴을 정의할 수 있는데, 이를 통해 코드를 간결히 만들고 타입 안정성을 늘릴 수 있다.
<return type> operator”” _<literal>(<arguments>
사용자 정의 리터럴은 위와 같은 문법에 의해 정의될 수 있다.
#include <iostream>
using namespace std;
class Dist {
public:
Dist(long double km): m_km(km) {
}
long double m_km;
};
long double operator"" _m(long double val) {
return val / 1000;
}
int main()
{
Dist d1(31000.0_m);
cout << d1.m_km;
return 0;
}
위 코드에서 생성자의 인자로 넘겨진 31000.0_m은 사용자 정의 리터럴에 따라 1000으로 나누어지고, 그 값에 따라 Dist가 초기화되는 것을 확인할 수 있다.
constexpr 키워드는 해당 표현식이 상수라는 것을 의미한다. 따라서 컴파일 타임에 그 값이 결정될 수 있다는 말이다. 이 표현식은 변수 뿐만이 아닌 함수에도 적용될 수 있다. constexpr을 사용하는 이유라고 하면 컴파일 타임에 연산이 끝나기 때문에 런타임 연산 속도가 빨라지기 때문이라고 할 것이다.
const와의 차이라고 한다면 const 키워드가 붙은 변수는 그 초기화가 상수로 주어지는게 아닌 이상은 런타임에 초기화 될 값이 정해지기 때문에 컴파일 타임에 그 값을 모를 수 있다.
함수에도 constexpr을 붙일 수 있다. 이 때 함수의 return type은 반드시 리터럴이어야 한다. 함수가 호출될 때 그 인자가 무조건 상수일 필요는 없다. 만약 상수일 경우 컴파일 타임에 그 값이 결정되며, 상수가 아닐 경우에는 런타임에 함수가 실행된다. 물론 그 값이 상수일 때만 그 결과를 constexpr로 취급할 수 있다.
초기화자 리스트는 동일한 타입 T에 대해서 오브젝트의 배열을 나타낼 수 있다. 실제 컨테이너는 아니지만 컨테이너같은 행위를 할 수 있다고 한다.
#include <iostream>
using namespace std;
class Bag {
public:
int item[10];
int size{0};
Bag(initializer_list<int> list) {
for(auto item : list) {
this->item[this->size++] = item;
}
}
};
int main()
{
Bag bag = {1, 2, 3, 4};
cout << bag.size;
return 0;
}
합격왕 우여곡절 끝에 드디어 합격왕에 광고를 붙였다. 서비스를 시작한지 무려 4년이 지나서야 드디어 광고를 시작하게…
반복적인 일상 매일 아침 일어나 회사에 출근하고, 저녁을 먹고 돌아오는 일상의 반복이다. 주말은 가족을 보러…
Planning A well-structured plan has the following characteristics: First, the ultimate vision you aim to…
English The most common problem for English learners like myself is that we often use…
This website uses cookies.