📔 오늘 공부한 내용

C++ 프로그래밍 공부를 계속해서 이어나갔다. 오늘은 스코프와 람다에 대한 내용을 위주로 공부를 진행했다.

스코프

C++을 배우다 보면 지역 변수, 전역 변수와 같은 내용들을 공부했을 것이다. Scope는 범위라는 뜻으로, 대부분의 언어에서 적용된다.

  • 스코프(Scope): 변수 또는 함수 등의 이름이 통용되는 범위를 말하며, 지역 변수의 소멸 시점과 관계가 깊다.
  • 전역 스코프: 함수 중괄호{...}가 없이 정의되거나 선언된 이름으로, 외부 링킹이 적용되어 extern 키워드를 통해 다른 소스코드에서도 접근이 가능하다.
  • 블록 스코프: 블록 밖에서 접근이 불가능하며, 블록을 벗어나면 자동으로 소멸된다.

일반적인 전역 변수는 전역 스코프, 블록 변수는 블록 스코프이다. 하지만, static으로 선언된 항목은 전역 변수이지만, 생성하는 위치에 따라 블럭 스코프일수도, 전역 스코프일수도 있다.

int x = 10;								// 전역 스코프, 전역 변수 (1)

int main(){
	
    for(int i = 0; i < n; i++) {		// i는 for문 블럭 스코프
    	static int sCounter = 0;		// 전역 변수이지만, 블럭 스코프
    }
    
    int x = 10;							// 여기서의 x는 지역변수 (2)
    
    x = 20;								// (2)의 변수 x를 사용
    ::x 20;								// 스코프 지정 연산자로, (1)의 변수 x를 사용
    
	...
}

클래스 스코프

클래스 멤버 정의 중에 static 키워드가 사용되면, 클래스 변수를 만드는 것이다. 클래스 변수는 전역 변수이지만, 클래스 스코프를 갖는다.

class A{
	public:
    	static int sCnt;				// 클래스 변수
        int id;							// 멤버 변수
        ...
};

int A::sCnt = 0;						// 클래스 변수는 전역 스코프에서 정의해야 함

namespace는 소프트의 경계를 만드는 도구이다. C++에서 프로그램을 작성할 때 기본으로 작성하다시피하는 using namespace std는 해당 코드의 기본 namespace를 std를 사용한다는 것을 의미한다.

  • std: iostream, vector 등 기본적인 코드 헤더에서 사용하는 네임스페이스
using namespace std;

int main(){
	cout << "test" << endl;
    
    std::cout << "test" << std::endl;	// namespace를 std로 정의했으므로, 이렇게 사용하지 않아도 된다.
}

람다(Lambda) 표현식

람다 표현식은 이름이 없는 익명의 함수를 정의하는 표현식을 말한다. 여러번 사용해야하는 함수가 아니거나, 초기화 시에만 필요한 함수의 경우에는 람다를 통해 작성하는 것이 더 빠르고 효율적이다.

  • 캡쳐: 람다 표현식 내부에서 외부의 값에 접근하기 위한 수단. 값 캡쳐는 묵시적으로 const로 취급되며, &를 붙여 참조 캡쳐가 가능함
  • 기본 캡쳐 모드: 스코프 내의 모든 이름을 일괄적으로 캡쳐하는 것. 위치한 블록에 노출된 모든 심볼을 캡쳐
  • 초기화 캡쳐: 클로져 클래스의 멤버 변수를 직접 초기화할 수 있도록 해주는 것으로 Right Value로 캐스팅 해 이동 생성 되도록 유도 가능(이동 전용 객체 등을 캡쳐할 때 사용)
# example 1
auto f = [&x, y](){						// x - 참조 캡쳐, y - 값 캡쳐

	return x += y;						// return 타입은 생략이 가능하다.
};

# example 2
auto f = [&](){...};					// 기본 캡쳐 모드(참조)
auto f = [=](){...};					// 기본 캡쳐 모드(값)

# example 3
struct Test{
	int x;
    auto returnClosure(){
    	return [=]() {return x;};		// x가 아닌 this 포인터가 캡쳐됨
    }
};

# example 4
auto pw = std::make_unique<Widget>();	// Widget은 bool 타입의 isValidate()와 isArchived()을 갖고 있을 때
auto func = [cpw = std::move(pw)] {		// 초기화 캡쳐
	return cpw->isValidated() && cpw-> isArchived();
};

참조로 캡쳐한 변수 또는 값 캡쳐한 포인터가 가르키는 대상이 소멸한 뒤 클로져가 실행될 경우, Dangling Pointer 버그가 발생할 수 있다.

📝 TIL을 정리하며

🤕 어려웠던 점

x가 아닌 this 포인터가 캡쳐된다는 점이 완벽하게 이해되지 않았다. Wandbox에서 여러번 코드를 돌려보며, 겨우 어느정도는 이해할 수 있었다.

🤔 궁금한 점

아직은 궁금한 점은 없었다.

😁 느낀 점

왜 배웠던 내용인데, 처음 보는 내용인 것 같은지... 이론은 항상 어려운것 같다. 수업에서 이론과 더불어 STL도 함께 매일매일 하고 있는데, 이 내용은 몰아서 한번에 작성하는게 좋을 것 같다.


📌 프로그래머스 데브코스 6기 자율주행 인지과정(Perception) 수강 내용을 바탕으로 정리한 TIL 입니다.
📅 Today: 2023. 9.20.

profile
그냥 끄적여보는 블로그

0개의 댓글