Right Value Reference 우측 값 참조

- 불필요한 메모리 복사를 방지하고 메모리를 이동시키는 방법

- 메모리의 할당, 복사, 해제 과정이 이루어지지 않아 성능향상

- move를 이해하기위해 필용한 개념인 것 같다.

 

좌측 값 (Lvalue) 와 우측 값 (Rvalue)

Lvalue = 7; 에서 좌측 값은 Lvalue이고 우측 값은 7 이다.

Lavlue2 = 31; 에서 좌측 값은 Lvalue2이고 우측 값은 31 이다.

 

Lvalue2 = Lvalue; 에서 Lvalue2는 좌측 값이다

Lvalue가 우측에 있기 때문에 우측 값이지 않을까? 라는 부분에서는

위의 식이 끝난 후에도 Lvalue의 값은 존재하므로 좌측 값이 된다.

 

우측 값과 좌측 값을 정확하게 구별하기 위해서는

식이 끝난 후에도 존재하면 좌측 값이고 존재하지않으면 우측 값이다 라고 알고 있으면 될 것같다.

 

좌측 값 참조

- 을 사용하여 좌측 값을 참조한다

Lvalue의 경우 좌측 값이므로 LeftValue 가 &을 사용하여 좌측 값을 참조 하였다.

7의 경우 우측 값이므로 LeftValue2가 &을 사용하여 좌측 값 참조를 하지 못하였다.

 

우측 값 참조

- && 을 사용하여 우측 값을 참조한다.

31의 경우 우측 값이므로 RightValue 가 &&을 사용하여 우측 값을 참조 하였다.

Lvalue의 경우 좌측 값이므로 RightValue 가 &&을 사용하여 좌측 값을 참조 하지 못하였다. 

'프로그래밍 공부 > modern C++' 카테고리의 다른 글

modern C++ Lambda  (0) 2022.02.25
modern C++ 범위 기반 for문 (rage-based for statement)  (0) 2022.02.18
auto  (0) 2022.02.17
스마트 포인터 weak_ptr  (0) 2022.02.17
스마트 포인터 shared_ptr  (0) 2022.02.15

람다 (Lambda)

- 익명함수

- 익명의 함수 객체를 정의

- 성질은 함수 객체와 동일하나 이름이 없는 함수

- 알고리즘이나 비동기 메서드에 전달하는 몇 줄의 코드를 캡슐화하는데 사용

- 타입을 가지고 있지만 decltype 나 sizeof를 사용할 수 없다.

 

람다 사용법

[captures](parameters){body}(call lambda);

[captures] 

캡처 조항(Capture Clause)

- 람다의 body에서 어떤 변수를 어떻게 사용할지 낱

종류 내용
[] 같은 영역에 있는 모든 변수 접근 불가
[&] 같은 영역에 있는 모든 변수를 참조로 캡처
[=] 같은 영역에 있는 모든 변수를 값으로 캡처
[변수 i] 같은 영역에 있는 변수 i 만 값으로 캡처, 나머지 다른 변수들에는 접근 불가
[&변수 i] 같은 영역에 있는 변수 i 만 참조로 캡처, 나머지 다른 변수들에는 접근 불가
[&, 변수i] 같은 영역에 있는 모든 변수를  참조로 캡처, 변수 i 만 값으로 캡처
[=, &변수i] 같은 영역에 있는 모든 변수를 값으로 캡처, 변수 i 만 참조로 캡처

 

[] 경우 같은 영역에 있는 변수 접근 불가

[&] 같은 영역에 있는 모든 변수를 참조로 캡처

[=] 같은 영역에 있는 모든 변수를 값으로 캡처

 

총 코드

#include<iostream>
using namespace std;

int main()
{
	/*[]() {cout << "hello world" << endl; }();
	[](int i) {cout << "int i : " << i << endl; }(7);

	auto sum = [](auto a, auto b) {return a + b; };

	cout << sum(3, 1) << endl;*/

	int a = 4;
	int b = 8;
	int c = 6;

	//같은 영역에 있는 모든 변수 접근 불가
	//[]() {cout << a << endl; }();
	/*[&]() {cout << a << endl; }();
	[&]() { a = 5; cout << a << endl; }();*/
	//[=]() {cout << b << endl; }();

	[c]() {cout << c << endl; }()
}

범위 기반 for문 (rang-based for statement)

- for문을 쉽고 안전하게 쓰기위한 방법

- 시작점과 끝점을 알려주지 않아도 처음부터 끝까지 순회 해주는 반복문

- c++11에서부터 사용 가능

- C#의 foreach문과 유사

 

 

사용방법

for(데이터 타입 element : 데이터 리스트)

{              

   element;

}              

단점

i = a[0];

i = a[1];

i = a[2];

    .      

    .      

i = a[9];

처럼 복사가 되어 값 변경이 불가능하고 복사비용이 발생

(이를 해결하기위해 const & 사용)

 

데이터 변경 시 참조형(&)으로 받아야 한다.

for(auto& i : arr)

{                      

      i = value;    

}                      

복사 비용 없이 값 변경방지 방법

for(auto const & i : arr)

{                                

     cout<< i <<endl;    

}                                

 

총 코드

#include<iostream>
using namespace std;

int main()
{
	int a[10] = { 1,2,3,4,5,6,7,8,9,10 };

	for (auto i : a)
	{
		cout << i << ", ";
	}
	cout << endl;
	cout << "값 변화 그냥하면 안됨" << endl;
	for (auto i : a)
	{
		i = 7;
	}
	for (auto i : a)
	{
		cout << i << ", ";
	}
	cout << endl;
	cout << "참조형으로 받으면 변경 가능" << endl;
	for (auto& i : a)
	{
		i = 7;
	}
	for (auto i : a)
	{
		cout << i << ", ";
	}
	cout << endl;

	for (auto const& i : a)
	{
		cout << i << ", ";
	}
	cout << endl;
}

'프로그래밍 공부 > modern C++' 카테고리의 다른 글

modern C++ R value reference 우측 값 참조  (0) 2022.03.01
modern C++ Lambda  (0) 2022.02.25
auto  (0) 2022.02.17
스마트 포인터 weak_ptr  (0) 2022.02.17
스마트 포인터 shared_ptr  (0) 2022.02.15

auto 란?

- 초기화 값에 따라 데이터 타입을 정해주는 키워드

- 명시적으로 type을 지정하지 않고 변수 정의 가능

- 컴파일 타임에 type이 결정된다.

- 초기화 할 때 type이 결정 되므로 초기화하지 않으면 error발생

//typeid(변수 이름).name() -> 자료형 출력

3. weak_ptr

- weak_ptr은 shared_ptr의 참조자이다.

- 하나 이상의 shared_ptr를 참조한다.

- use_count를 증가, 감소 시키지않는다.

(weak reference count 증가 -> 객체 소멸에 관여하지않음)

(string reference count 증가하지않음 -> 객체 소명에 관여)

- shared_ptr 순환 참조 문제를 해결하기 위해 사용

 

*순환 참조(circular reference) 문제

서로가 서로를 가르키는 shared_ptr은 reference count가 0이 될 수가 없어

메모리가 해제되지않는 문제

 

사용법

#include<memory> 추가

weak_ptr<객체> 스마트 포인터 명 = shard_ptr객체;

 

총 코드

#include<iostream>
#include<memory>
#include<string>
using namespace std;

class Person
{
	string name;
	int age;
public:
	Person(const string& name, int age);
	~Person();
	void ShowData();
};

Person::Person(const string& name, int age)
{
	this->age = age;
	this->name = name;
	cout << "Person 생성자 생성" << endl;
}

Person::~Person()
{
	cout << "Person 소멸자 생성" << endl;
}

void Person::ShowData()
{
	cout << "나이 : " << age << endl;
	cout << "이름 : " << name << endl;
}

int main()
{
		shared_ptr<Person> Lee(new Person("JaeWoo", 31));
		Lee->ShowData();
		cout << "reference count : " << Lee.use_count() << endl;
	
		weak_ptr<Person> Lee2 = Lee;
		cout << "reference count : " << Lee.use_count() << endl;

		auto sharedLee(Lee);
		cout << "reference count : " << Lee.use_count() << endl;

		Lee2.reset();
		cout << "reference count : " << Lee.use_count() << endl;

}

'프로그래밍 공부 > modern C++' 카테고리의 다른 글

modern C++ 범위 기반 for문 (rage-based for statement)  (0) 2022.02.18
auto  (0) 2022.02.17
스마트 포인터 shared_ptr  (0) 2022.02.15
스마트 포인터란? && unique_ptr  (0) 2022.02.13
Modern C++ 이란?  (0) 2022.02.12

2.  shared_ptr

- 하나의 객체를 참조하는 스마트 포인터의 갯수를 참조하는 스마트 포인터

- 참조 횟수(reference count) : 새로운 shared_ptr 추가시 1증가, 제거시 1감소

- 참조 횟수가 0이 되면 메모리를 자동으로 해제

 

사용법

#include<memory> 추가

shared_ptr<객체>스마트 포인터 명(new 객체);

shared_ptr<객체>스마트 포인터 명 = make_shared<객체>(인수);

shared_ptr 객체 Lee를

sharedLee로 참조하여 레퍼런스 카운터가 2가 되었고

Lee를 해제시 sharedLee가 같은 값을 참조하고 있으므로 데이터는 삭제되지않고 

러퍼런스 카운터만 1 줄어든다.

 

총 코드

#include<iostream>
#include<memory>
#include<string>
using namespace std;

class Person
{
	string name;
	int age;
public:
	Person(const string& name, int age);
	~Person();
	void ShowData();
};

Person::Person(const string& name, int age)
{
	this->age = age;
	this->name = name;
	cout << "Person 생성자 생성" << endl;
}

Person::~Person()
{
	cout << "Person 소멸자 생성" << endl;
}

void Person::ShowData()
{
	cout << "나이 : " << age << endl;
	cout << "이름 : " << name << endl;
}

int main()
{
	shared_ptr<Person> Lee(new Person("JaeWoo", 31));
	Lee->ShowData();
	cout << "reference count : " << Lee.use_count() << endl;

	auto sharedLee(Lee);
	cout << "reference count : " << Lee.use_count() << endl;

	Lee.reset();
	cout << "reference count : " << sharedLee.use_count() << endl;

	shared_ptr<Person> Lee2 = make_shared<Person>("JaeWoo", 31);
	Lee2->ShowData();
	cout << "reference count : " << Lee2.use_count() << endl;
	auto sharedLee2(Lee2);
	cout << "reference count : " << Lee2.use_count() << endl;
	sharedLee2.reset();
	cout << "reference count : " << Lee2.use_count() << endl;
}

'프로그래밍 공부 > modern C++' 카테고리의 다른 글

modern C++ 범위 기반 for문 (rage-based for statement)  (0) 2022.02.18
auto  (0) 2022.02.17
스마트 포인터 weak_ptr  (0) 2022.02.17
스마트 포인터란? && unique_ptr  (0) 2022.02.13
Modern C++ 이란?  (0) 2022.02.12

스마트 포인터 (Smart Pointer)

- 포인터처럼 동작하는 클래스 템플릿

- 메모리를 자동으로 해제

 

스마트 포인터 종류

c++98  -> auto_ptr   //c++11 표준부터 삭제

c++11 이후 -> unique_ptr, shared_ptr, weak_ptr

 

1. unique_ptr

- 하나의 스마트 포인터만이 특정 객체를 소유할 수 있다.

- 해당 객체의 소유권을 가지고 있을 때만 소멸자가 해당 객체를 삭제할 수 있다.

- 복사 생성자와 복사 대입연산자가 구현되어 있지않아 복사가 불가능하다.

- move()멤버 함수를 통해 소유권을 이전(이동)할 수 있다. 

- 소유권을 이전(이동)한 스마트 포인터는 해당 객체를 소유하지 않게 된다.

 

사용법

#include<memory> 추가

unique_ptr<객체> 스마트 포인터 명(new 객체);

unique_ptr<객체> 스마트 포인터 명 = make_unique<객체>(인수);      //make_unique  c++14부터 표준으로 추가

unique_ptr 사용법

move();  -> 이동

get(); -> 얻기

reset();  -> 해제

-> Lee 값에서 Lee2 값으로 move() 하였으므로

-> Lee 값은 nullptr 이고 Lee2 값이 Lee 값을 가지게 되었다.

 

make_unique()

- 전달 받은 인수를 사용해 지정된 타입의 객체를 생성하고 생성된 객체를 가리키는 unique_ptr을 반환

 

총 코드

#include<iostream>
#include<memory>
#include<string>
using namespace std;

class Person
{
	string name;
	int age;
public:
	Person(const string& name, int age);
	~Person();
	void ShowData();
};

Person::Person(const string& name, int age)
{
	this->age = age;
	this->name = name;
	cout << "Person 생성자 생성" << endl;
}

Person::~Person()
{
	cout << "Person 소멸자 생성" << endl;
}

void Person::ShowData()
{
	cout << "나이 : " << age << endl;
	cout << "이름 : " << name << endl;
}

int main()
{
	//unique_ptr<객체> 스마트 포인터 명(new 객체);
	unique_ptr<Person> Lee(new Person("JaeWoo", 31));
	//Lee->ShowData();

	//auto Lee2 = Lee;
	cout << "Lee 값 : ";
	cout << Lee.get() << endl;
	cout << "Lee2 로 이동" << endl;
	auto Lee2 = move(Lee);
	cout << "Lee2 값 : ";
	cout<<	Lee2.get()<<endl;
	cout << "이동 후 Lee 값 : ";
	cout << Lee.get() << endl;
	cout << "Lee2 해제하여 소멸자 호출 "<<endl;

	Lee2.reset();
	cout << Lee2.get() << endl;

	//unique_ptr<객체> 스마트 포인터 명 = make_unique<객체>(인수); 
	//unique_ptr<Person> Kim = make_unique<Person>("Moon", 30);
	//Kim->ShowData();
}

 

'프로그래밍 공부 > modern C++' 카테고리의 다른 글

modern C++ 범위 기반 for문 (rage-based for statement)  (0) 2022.02.18
auto  (0) 2022.02.17
스마트 포인터 weak_ptr  (0) 2022.02.17
스마트 포인터 shared_ptr  (0) 2022.02.15
Modern C++ 이란?  (0) 2022.02.12

C++98/03, C++11/14 와 같이

98년도에 표준화 03년도에 추가, 수정

11년도에 표준화 14년도에 추가, 수정 과 같이 

여러 최신 기능들을 추가하고 수정하여 표준화하는데

C++11/14 부터 mordern C++ 이라고 부른다.

 

안정성과 성능향상 등의 장점이 있고

 

- 스마트 포인터

- auto

- Ranged-vased for 반복자

- constexpr

- r-value / move

- Lambda

등등을 사용

 

'프로그래밍 공부 > modern C++' 카테고리의 다른 글

modern C++ 범위 기반 for문 (rage-based for statement)  (0) 2022.02.18
auto  (0) 2022.02.17
스마트 포인터 weak_ptr  (0) 2022.02.17
스마트 포인터 shared_ptr  (0) 2022.02.15
스마트 포인터란? && unique_ptr  (0) 2022.02.13

+ Recent posts