주인장 공지입니다. Lu's…〃 Diary。

반갑습니다. 루사인이라고 합니다.


1. 책 리뷰 & 프로그래밍 일기 블로그입니다.

2. 가끔 성과 글도 올라와요.

3. @Lusain_Kim 에 상주 중.



환영합니다.

[C++] 변수를 읽어보자 Lu's…〃 Programing。

 C++ 어렵게 하는 요소 중에는 변수를 읽는 방법이 난해하다는 점이 있고, 비중은 것이다.

 

 변수를 읽는 법은 입문 직후가 아니라 어느 정도 C++ 했다 싶은 사람들의 발목을 잡는다. 입문자는 int* 무엇인지 모르지만 이건 포인터를 모르는 거지 이를 읽는 방법을 모르는 것이 아닐 것이다.

 

 예를 들어보자. 포인터로 int 타입의 값을 인자로 넘겨받아 확인하고 싶다. 참조하는 값을 변경하고 싶지 않아서 const 붙이려고 한다. 어떻게 써야 할까?

 

  1. const int *
  2. int * const
  3. int const *
  4. int const * const

 

 정답은 2번을 제외한 전부이다. 결론만을 말하자면, 1번과 3번은 완전히 동일한 타입이고 4 역시 참조만 목적이면 사용이 가능하다.
 

 

 

 변수를 읽는 방법은 생각보다 간단하다. 변수 이름을 적는 오른쪽부터 왼쪽으로 읽어가면 된다. 구분은 참조(&) 포인터(*) 단위로 하고, cv-identifier(const / volatile) 타입의 또는 뒤에 자유롭게 온다.

 

예를 들어, const char * const * A; 같은 미친 문법이 있다. 실제로 이런 문법을 쓰지는 않지만. A 타입을 읽으면 다음과 같다.

 

 A 포인터(인데, 어떤 타입의 포인터냐면) const 타입의 포인터(인데, 어떤 타입의 포인터냐면) const char 타입.

 

 이해가 가지 않는가? 그러면 C++11 using(아니면 typedef) 사용해서 구체화해보자.

 

using Type = const char;

using TypePtr =Type*;

using constTypePtr =const TypePtr;

using Ty = constTypePtr*;

 

Ty B;

 

B 타입은 const char* const * 된다. A 동일하게 되는 것이다.

예제는 일부러 많이 나누기도 했지만, 너무 복잡하고 타입은 using으로 간략화 하는 편이 정신건강과 생산성을 챙기는 방법이 것이다


C++'s Move Semantics Lu's…〃 Programing。



학내 강연을 목적으로 만든 PPT입니다.
C++의 이동의미론이 주제지만 C++의 참조에 대해 이야기를 다루었습니다.
질문이나 건의 사항은 댓글 혹은 sain9212@gmail.com 으로 부탁드리겠습니다.


Windows 10의 테마 컬러 얻기(C++) Lu's…〃 Programing。


<차례대로 설정 앱, 작업 표시줄의 시계를 누르면 나오는간이 앱, 시작 버튼을 나오는 UI>

 

Windows 8부터 테마 색이라는 생겼는데( 이전일 수도 있다), 이름 그대로 Windows 전반에서 색이 들어가는 곳에 통일된 색을 사용한다. 색을 어떻게 얻을까?

 

 

내가 찾은 방법은 UWP(UniversalWindows Platform) 사용하는 것이다.

UWP 코드는 Microsoft 확장 C++(C++/CLI C++/CX;현재 명칭) 또는 C#(권장)으로 구현되었기 때문에, nativeC++(C++/CLR)에서는 사용하지 못한다. 혹시라도 사용하는 방법이 있다면 댓글로 남겨주면 고맙겠다.

 

 

 

우선, 테마 색을 얻는 코드를 보자. MSDN C#으로 나온다. 

https://docs.microsoft.com/en-us/windows/uwp/style/color

 

코드를 보자.

 

void accentColorUpdated(FrameworkElementelementWithText)

{

    var uiSettings= new Windows.UI.ViewManagement.UISettings();

    Windows.UI.Color c =uiSettings.GetColorValue(UIColorType.Accent);

 

    bool colorIsDark= (5 * c.G + 2 * c.R + c.B) <= 8 * 128;

    if (colorIsDark)

    {

        elementWithText.RequestedTheme =ElementTheme.Light;

    }

    else

    {

        elementWithText.RequestedTheme =ElementTheme.Dark;

    }

}

 

Windows.UI.ViewManagement.UISettings 이라는 클래스가 있는데, 클래스의 인스턴스에서 GetColorValue 함수를 사용하니 색이 얻어진다고 한다. ...????? 이걸 어떻게 .

 

C++/CX 사용해본 사람은 알겠지만, 이걸 C++/CX 바꿀 있다.

 

다음은 핵심 코드 부분이다. 우리는 윈도우 테마 색을 얻으면 되기 때문에 C# 코드와는 내용이 다르다.

 

#include <roapi.h>

#include<rometadata.h>

#include <windows.ui.viewmanagement.h>

 

using namespace Windows::UI::ViewManagement;

 

Windows::UI::Color GetWindowsThemeColor()

{

    UISettings ui= ref new UISettings();

    Windows::UI::Color color = ui->GetColorValue(UIColorType::Accent);

    return color;
}

 

코드면 색이 얻어지는데, 유감스럽게도 C++/CLR에서 색을 얻고 싶은 사람들이 있을 것이다. 이럴 때는 가지 방법 하나를 택하면 된다.

 

  1. 참에 프로젝트를 C++/CX 짜볼까?
  2. 외부 라이브러리로 빼자!

 

 2 어려우니 1 선택했지만 웬걸, C++/CX 코드 써도 컴파일이 안된다. 어째서?

아직은 C++/CX 거지 Windows 10 API 아니다. C++/CX에서 Windows 10 API 쓰는 방법을 알아보자.

 

데스크톱 응용 프로그램에서 Windows 10 API 호출 - Windows 용 응용 프로그램 만들기 Windows 용 응용프로그램 빌드https://blogs.windows.com/buildingapps/2017/01/25/calling-windows-10-apis-desktop-application/

 

영어라고 슬퍼하지 말자. 구글 번역기로 거의 해석이 되는 수준이다.

 

핵심적인 내용만 뽑는다.

 

  1. 프로젝트 속성 > C/C++ > Windows 런타임 확장 사용 > (/ZW)
  2. 추가 using 디렉터리에 다음 값들을 추가한다. Visual Studio 2017 기준이고, 설치 경로를 바꿨으면 적절하게 변경해서 넣어주자.
    • C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcpackages
    • C:\Program Files (x86)\Windows Kits\10\UnionMetadata
    • C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\1.0.0.0
    • C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.FoundationContract\1.0.0.0

 

  1. C/C++ > 코드 생성 > 최소 다시 빌드 가능 > 아니요(/Gm-)
  2. 프로젝트 속성 > 구성 속성 > 일반 > Windows SDK 버전을 Windows 10 버전으로 바꾼다. 시작이 10이면 어떤 버전이든 상관이 없다.

 

 여기서 커다란 문제가 생기는데, 별도로 Windows 10 SDK 설치하지 않은 사람들은 Windows 10 버전이 없을 것이다. 결국 이거 하나 때문에 Windows 10 SDK 깔아야 하나 고민을 하게 것인데, 사실 이거 하나 때문에 깔기에는 용량 부담이 크긴 하다. 깔고 있는 방법이 있다면 부디 댓글로 알려주길 바란다.

 

 여하튼, 여기까지 따라온 사람들은 코드 넣고 돌려보자. 아마 것이다.

 

 참조한 블로그에 들어가면(Windows 공식 블로그일 것이다) 예제 소스코드까지 해서 있으니 따라해보자





<위쪽이 내가 만든 시계 프로그램. Win32 응용프로그램이. 테마 색이 적용된 것을 있다>


PS.1 - 날짜 색깔은 AccentLight1이더라. 이거 못찾고 한참 헤맸다.
PS.2 - 참조 프로젝트를 C++/CX 프로젝트로 만들고 외부에서 사용하는 방식으로 C++/CLR 프로젝트에서 사용할 수 있다.
[Visual Studio] 참조 프로젝트를 만들어보자 | http://lusain.egloos.com/3163505


[C++11] R-Value와 이동 의미론(move semantics) Lu's…〃 Programing。


C++11 되며 일반적으로 값으로 알고 있던 개념을 L-ValueR-Value 분류하였다.

 

L-Value R-Value 다음과 같이 생각하면 된다.

 

int I = 5; 에서,

L-Value

i

이름이 있고 지속되는

R-Value

5

해당 줄에서만 살아있는 임시

 

 추가적으로, int i = make_int( 10 ); 이라는 코드에서 make_int( 10 ) 역시 R-Value이다.

이름을 가지지 않았고, 지속되지 않기 때문이다.

가장 단순한 R-Value 확인 방법은 앞에 주소 연산자(&) 붙여보는 것이다.
  R-Value 지속되지 않기 때문에 L-Value 참조를 없다.

 

 R-Value 지원하게 되자 가지 이득이 생겼다.

 

  1. 임시 값은 L-Value 참조를 없다. 그런데 R-Value 참조가 생기며 문제가 해결됐다.
  2. L-Value 참조 연산이 아닌 R-Value 참조 연산이 추가되었다.
    L-Value
    참조 생성자/할당자는 연산 후에도 매개인자의 값이 남기 때문에 복사 연산이라고 부르지만, R-Value 참조 생성자/할당자는 연산 매개인자의 값이  남지 않기 때문에( 임시 값이기 때문에) 이러한 연산을 이동 연산이라고 한다.
  3. 유일한 소유권(원본의 복사가 불가능하도록) 구현할 있게 되었다.
  4. 이상 사용되지 않을 L-Value 값을 이동 연산을 사용하여 비울 있다.
    • 임시 값이 아니지만, std::move 연산으로 임시 값처럼 만들 있다.
    • R-Value 캐스팅을 해도 값이 이동하지는 않는다. 이동 처리를 직접 작성해야 한다.
    • 이동연산을 수행한 값은 (이동 연산의 구현 목적대로 구현했다면) 비워진 상태이므로 사용하면 된다.

 

 

 

R-Value 사용하는 가장 좋은 예는 STL(StandardTemplate Library)에서 찾을 있다.

  1. STL Container들의 emplace 연산은 Element 이동 생성자를 지원하면 이동 생성을 한다.
    • 대부분의 STL Container std::Container < Element > 표현된다.
    • 이동 생성자를 지원하지 않거나, 이동 생성자에 예외가 없지 않을 경우(noexcept 키워드가 없을 경우) 복사 생성자가 호출된다.
  2. 소유권이 유일해야 하는(복사되면 되는) 객체를 만들 사용할 있다.
    표준 라이브러리 unique_ptr shared_ptr에서 사용한다.
    • shared_ptr 경우에는 shared_ptr 객체 내부에서만 소유권을 공유해야 하므로 외부 객체로 shared_ptr 만들기 위해서는 객체를 이동 연산으로 생성하여 외부 객체를 비워야 한다.
    • 복사 생성/복사 할당 금지는 소유권을 정해 소멸 책임을 확실히 있다.

 

 

 

  외에도 객체의 내부를 건들지 않고 객체를 이동시킬 불필요한 객체의 복제를 시행하지 않게 하여 낭비를 줄일 있게 되었다.

 

 

 

 그렇다면 R-Value 어떻게 참조할 있는가?

L-Value 참조는 &(앰퍼런트) 붙였다.

R-Value L-Value보다늦게 들어왔기 때문에, & 하나 붙는다. 반쯤 농담이지만 정말 붙었다.

 

 

type-id && expression= R-Value;

 

  1. 그럼 R-Value Reference R-Value일까, L-Value일까?

 

 

 

  1. 정답은 L-Value이다. 지속되거든.

 

 그렇기 때문에 R-Value Reference std::move 함수로 R-Value 캐스팅해줘야 한다.

만약 매개인자로 받은 R-Value Reference 이동 외에 사용해야 한다면 이동하기 전에 사용해야 한다.

 


 

 여기까지 정리를 하자면

 

  1. C++11부터 R-Value 개념이 도입되었다.
  2. R-Value 임시 값이다. 함수의 반환 , 원시 상수 이름이 없고 지속되지 않는 의미한다.
  3. L-Value R-Value처럼 std::move라는 함수로 캐스팅할 있다.
    함수 이름이 std::move라고 정말 객체가 이동하지는 않는다.
  4. R-Value 참조를 매개 인자로 받는 생성자/할당자를 만들 있다. 이는 이동 생성자/할당자라 한다.
  1. 이동 연산은 이름대로 값을 이동시키지 않는다. 이동은 직접 구현해야 한다.
  2. 기본 타입(Primitive Type : int, short, float, double, char ) 소멸자도, 어떤 생성자도 없는 구조체의 이동 연산은 복사와 동일하다.
    • 확실하지는 않다. 정확한 레퍼런스를 아시는 분은 알려주시면 감사하겠습니다.

 

소결론.

R-Value 참조를 사용한 이동 연산은 특수한 형태의 복사 연산이다.

 

 다만 경우에 따라 최적화할 있는 방법이 있으면 조금이라도 최적화를 하자는 뜻으로 만드는 것이다.

 

 


참고하면 좋은 곳:

1. MSDN : https://msdn.microsoft.com/ko-kr/library/dd293665.aspx




next▷ universal Reference



1 2 3 4 5 6 7 8 9 10 다음