일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- virtual destructor
- base from member
- dynamic_cast
- c++ multi chatting room
- 더 지니어스 양면포커
- c++ basic practice
- std::vector
- placement new
- diamond inheritance
- pointer to member data
- std::cout
- delete function
- virtual inheritance
- virtual function
- member function pointer
- new&delete
- discord bot
- constructor
- return by reference
- std::ostream
- vector size
- conversion constructor
- C++
- this call
- virtual function table
- vector capacity
- increment operator
- operator overloading
- suffix return type
- std::endl
- Today
- Total
I'm FanJae.
[C++] 연산자와 제어문 본문
※ 본 포스트는 코드누리 C++ Basic 강의 내용을 보고 정리한 포스트입니다.
- C++에서 새롭게 추가된 for문이 존재한다.
1. range for
1-1. std::size() // C++ 17
일반적으로, for를 사용할 때, 배열의 크기가 바뀌면, for 안의 크기도 바뀌어야 했다.
그때 C 언어에서 가장 많이 사용한 방식이 아래 방식이다.
#include <iostream>
int main(void)
{
int x[10] = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < sizeof(x) / sizeof(x[0]); i++)
{
std::cout << x[i] << ", ";
}
}
C++에서는 std::size 라는 것이 존재한다.
#include <iostream>
int main(void)
{
int x[10] = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < std::size(x) ; i++)
{
std::cout << x[i] << ", "
}
}
- 이와 같이 사용이 가능하다. std::size()는 배열 크기를 구하는 C++ 표준 함수이다.
- 배열 뿐 아니라, C++ 표준 라이브러리(STL)의 다양한 컨테이너의 크기도 구할 수 있다.
1-2. range-for // C++ 11
#include <iostream>
int main(void)
{
int x[10] = {1,2,3,4,5,6,7,8,9,10};
//for ( int e : x ) // range-for
for ( auto e : x ) // auto로 바꿔주면, x의 데이터 타입이 바뀌는 것에 유연하게 대처할 수 있다.
{
std::cout << e << ", ";
}
}
- C++11 부터 지원되는 새로운 형태의 for이다.
- 배열 뿐 아니라 다양한 STL 컨테이너도 이를 사용할 수 있다.
- 이는 C++ 뿐 아니라 Python, Java, C# 등에서도 이런 형태의 문법을 확인할 수 있다.
1-3. range-for Reverse
#include <iostream>
#include <ranges>
bool is_odd_number(int n) { return n % 2 == 1; }
int main()
{
int x[10] = {1,2,3,4,5,6,7,8,9,10};
for (auto e : x)
{
std::cout << e << ", ";
}
}
- 위 예제는 x를 정방향으로 출력하는 것이다.
- range-for를 이용해서 이를 거꾸로 출력하는 것은 C++ 20 이전에는 별도로 제공하지 않았다.
- C++20부터는 Ranges Library를 사용하여 해결할 수 있다.
- <ranges> 헤더파일을 포함하여, std::views namespace 안에 다양한 함수를 제공한다.
① std::views::reverse
// for (auto e : x)
for (auto e : std::views::reverse(x))
- for 부분을 위와 같이 수정하면, x의 요소를 하나씩 넣어줄때, 거꾸로 넣어줄 것이다.
② std::views::take
// for (auto e : x)
for (auto e : std::views::take(x, 3))
- std::views::take를 이용하면, 지정한 원소 개수만큼만 꺼내는 것도 가능하다.
// for (auto e : x)
for (auto e : std::views::reverse( std::views::take(x, 3)))
- 이와 같이 중첩도 시킬 수 있다.
③ std::views::drop
// for (auto e : x)
for (auto e : std::views::drop(x, 3))
- drop은 해당 개수만큼 제외하고, 넣으라는 의미가 된다.
④ std::views::filter
// for (auto e : x)
for (auto e : std::views::filter(x, is_odd_number))
- filter는 x에 있는 원소를 차례대로 함수(is_odd_number)에 보내서 참인 값만 반환해준다.
// for (auto e : x)
for (auto e : std::views::filter(x, [](int n) { return n % 2 == 1; } ) )
- Lambda expression을 사용하는 것도 당연히 가능하다.
※ Ranges Library에 대한 자세한 내용은 STL에서 다뤄보고자 한다.
2. if with initializer // C++ 17
- C++17 에서는 if 문에 초기화 구문을 넣을 수 있다.
int foo()
{
return 0;
}
int main()
{
int ret = foo();
if ( ret == 0 )
{
}
// C++17
if ( int ret = foo(); ret == 0)
{
}
}
- 이처럼 if문 안에서 초기화 구문 선언이 가능하다.
- 이때의 ret 변수의 수명은 if문 블록을 벗어나는 순간 소멸된다.
switch( int n = foo(); n)
{
case 1: break;
}
- switch 에서도 사용할 수 있다.
// C++20
for( int x[3] = {1,2,3}; auto n : x)
{
}
- C++20부터는 range - for 도 사용이 가능하다.
3. new
#include <iostream>
#include <cstdlib>
int main()
{
int* p1 = (int*)malloc(sizeof(int));
free(p1);
int* p2 = new int;
delete p2;
int* p3 = new int[10];
delete[] p3;
}
- C 언어에서는 동적 메모리 할당시 malloc 함수를 사용했고, 해제시에는 free를 사용했다.
- C++ 언어에서 이를 사용해도 되나, new와 delete를 이용해 더 간단하게 할당 및 해제가 가능하다.
3-1. 동적 메모리 할당 방법
// C
int *p1 = (int *) malloc(sizeof(int));
free(p1);
// C++
int *p2 = new int;
delete p2;
3-2. malloc vs new
C | malloc | new |
정체 | 함수 | 연산자(키워드) |
인자 | 할당할 메모리 크기 | 타입 |
반환타입 | void *, 캐스팅 필요 | 전달 타입의 포인터, 캐스팅 필요 없음. |
해지방법 | free | delete 또는 delete[] |
생성자 | 생성자가 호출 되지 않음 | 생성자가 호출됨. |
- malloc과 new의 결정적인 차이는 생성자 호출 여부에 있다.
※ 배열 형태로 메모리를 할당한 경우 반드시 delete[] 로 회수해야 한다. delete로 해지할 경우, undefine(미정의 동작)으로 발생한다.
4. three way comparsion operator // C++20
#include <iostream>
int main()
{
double n1 = 30, n2 = 20;
bool b1 = (n1 < n2);
auto ret = (n1 <=> n2); // C++20
if ( ret == 0 )
std::cout << "n1 == n2" << std::endl;
else if ( ret > 0 )
std::cout << "n1 > n2" << std::endl;
else if ( ret < 0 )
std::cout << "n1 < n2" << std::endl;
// std::cout << ret << std::endl;
std::cout<< typeid(ret).name() << std::endl;
}
- 우주선(spaceship) 연산자라고도 불리는 연산자이다.
- auto ret = (n1 <=> n2); 와 같이 사용한다.
- ret의 비교결과는 다음과 같다.
ret == 0 | n1과 n2는 같다. |
ret > 0 | n1이 n2보다 크다. ( n1 > n2 ) |
ret < 0 | n1이 n2보다 작다. ( n1 < n2 ) |
4-1. <=> 연산자의 반환 타입
- 반환 값을 std::cout로 출력할 수 없다.
- typeid라는 것을 사용하여 타입을 확인할 수 있다.
- 어떤 타입을 비교하는지에 따라 반환 타입이 달라진다. 이 때문에 auto로 받을 수 밖에 없다.
- std::strong_ordering, std::weak_ordering,std::partial_ordering 등으로 나온다.
※ 다소 복잡한 얘기가 있어, <=>에 대해서는 추후 별도 포스트로 다루고자 한다.
'C++ > Basic' 카테고리의 다른 글
[C++] nullptr (0) | 2024.08.11 |
---|---|
[C++] Reference (0) | 2024.08.09 |
[C++] Function III (0) | 2024.08.08 |
[C++] Function III (0) | 2024.08.08 |
[C++] Function II (0) | 2024.08.08 |