- 이미지의 포맷 변환 및 퀄러티, 크기조정(비율) 모듈 
- Windows 환경, C++, GDI+, Component


STDMETHODIMP CMobileImage::Convert(BSTR Src, BSTR Output, BSTR ImgFormat, long Quality, long Width, long Height, VARIANT_BOOL* pSuccess)
{
*pSuccess = VARIANT_FALSE;

_bstr_t bstrSrc(Src);
_bstr_t bstrOutput(Output);
_bstr_t bstrImgFormat(ImgFormat);

ULONG_PTR gdiToken;
Gdiplus::GdiplusStartupInput gdiInput;
Gdiplus::GdiplusStartup(&gdiToken, &gdiInput, NULL);

try {
std::auto_ptr<Gdiplus::Image> pImage(Gdiplus::Image::FromFile((LPCWSTR)bstrSrc));
if (!pImage.get()) {
throw -1;
}

CLSID m_pngClsid;
if (GetEncoderClsid((LPCWSTR)ImgFormat, &m_pngClsid) == -1) {
throw -1;
}
else {
Gdiplus::EncoderParameters params;
params.Count = 1;
params.Parameter[0].Guid = Gdiplus::EncoderQuality;
params.Parameter[0].Type = Gdiplus::EncoderParameterValueTypeLong;
params.Parameter[0].NumberOfValues = 1;

long Value = Quality;
params.Parameter[0].Value = &Value;

if (Width > 0 && Height > 0) {
std::auto_ptr<Gdiplus::Bitmap> pResize(new Gdiplus::Bitmap(Width, Height, PixelFormat24bppRGB));
std::auto_ptr<Gdiplus::Graphics> pGrap(Gdiplus::Graphics::FromImage(pResize.get()));
pGrap->DrawImage(pImage.get(), 0, 0, Width, Height);

pResize->Save((LPCWSTR)bstrOutput, &m_pngClsid, &params);
}
else {
pImage->Save((LPCWSTR)bstrOutput, &m_pngClsid, &params);
}
}

*pSuccess = VARIANT_TRUE;
}
catch (...) { }

Gdiplus::GdiplusShutdown(gdiToken);

if (m_spObjectContext) { m_spObjectContext->SetComplete(); }

return S_OK;
}


int CMobileImage::GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
using namespace Gdiplus;

UINT  num = 0;          // number of image encoders
UINT  size = 0;         // size of the image encoder array in bytes

ImageCodecInfo* pImageCodecInfo = NULL;

GetImageEncodersSize(&num, &size);
if(size == 0)
return -1;  // Failure

pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return -1;  // Failure

GetImageEncoders(num, size, pImageCodecInfo);

for(UINT j = 0; j < num; ++j)
{
if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j;  // Success
}    
}

free(pImageCodecInfo);
return -1;  // Failure
}

'Dev > C++' 카테고리의 다른 글

boost 설치  (0) 2013.11.20
boost::asio 클라이언트 소켓 (timeout 기능)  (0) 2010.10.14
C++0x, RValue Reference  (0) 2009.05.27
C++0x Lambda  (0) 2009.05.20
C++0x 지원 컴파일러 목록  (0) 2009.05.20

2021년 신규 작성 

CryotoPP Example - cdeclog

 

CryotoPP Example

CryptoPP https://www.cryptopp.com/ Crypto++ 사용하기, 예제 암호화 지식 (개발자)

cdecl.github.io

 

--

C++ 용 암호화 라이브러리
 
Crypto++ 컴파일 
 
우선 해당 사이트에서 라이브러리를 다운 받은 후 원하는 컴파일러로 컴파일을 하여 dll 이나 lib 파일을 생성한다.
VC++ 2008 버전의 경우 프로젝트 파일이 따로 있지는 않고 VC++2005 버전을 업그레이드 후 컴파일 하면 됨
 
컴파일을 하면 cryptopp560\Win32 디렉토리에 각각 파일이 생성되고, dll 의 경우는 cryptopp560\Win32\DLL_Output 폴더에, static library 의 경우는 cryptopp560\Win32\Output 폴더에 각각의 모듈이 생성 된다. 
 
내가 테스트 할때는 dll 의 버전의 경우 이상하게 링크에러가 발생을 하여,
static library 를 사용하여 테스트를 하고 어플리케이션의 경우도 static library 로 컴파일을 해야 문제가 없었다.
 
블록 알고리즘 고려사항 
알고리즘 종류, 블록 알고리즘 운영 모드, 패딩종류, 인코딩 (텍스트 암호화의 경우)
 
알고리즘 SEED, AES, DES, 3-DES 설명 
 
 
DES
가장 오래되고, 세계적으로 가장 널리 사용되는 고전적 암호화 알고리즘이다. 파일이나 패킷을 암호화할 때 많이 사용된다. 하지만, 64비트 입력 블록과 56비트 짧은 비밀키를 사용하기 때문에, 더 이상 안전하지 않다고 간주하고 있다. 그러나, 국가 기밀을 다룰 정도로 극히 중요한 보안이 아니라면, 여전히 가장 널리 사용되는 알고리즘이다.
 
3-DES
DES를 3번 반복해서 암호화한다. 보안성이 향상되고, 그 만큼 성능은 떨어진다.
 
AES
미국 NIST에서 공모해서 표준화한 새로운 알고리즘이다. 128비트 입력 블록을 도입함으로써, 보안성을 향상했으며, 최근에 세계적으로 널리 사용되는 알고리즘이다.
 
SEED
KISA 주관으로 ETRI와 함께 국내에서 만들어진 알고리즘이다. 역시, 128비트 입력 블록을 사용하고 있고, 국제 표준에 부합하는 알고리즘이다.
 
 
 
 
블록 알고리즘 운영 모드 
 
ECB(Electronic codebook) : 평문을 일정 크기의 블록으로 나누어서 처리, 각 블록은 동일한 키로 암호
CBC(Cipher-block chaining) : 평문 블록과 바로 직전의 암호블록을 XOR한 것. 첫번째 암호 블록을 위해 초기 벡터 IV 값 사용
 
기타..
PCBC(Propagating cipher-block chaining)
CFB(Cipher feedback)
OFB(Output feedback)
CTR(Counter)
 
 
패딩(Padding) 종류
 
enum BlockPaddingScheme 
{NO_PADDING, ZEROS_PADDING, PKCS_PADDING, ONE_AND_ZEROS_PADDING, DEFAULT_PADDING};
 
NO_PADDING : 패딩 없음
ZEROS_PADDING : NULL(0) 으로 패딩 
PKCS_PADDING : 패딩되는 바이트의 수의 같은 값으로 모두 패딩
ONE_AND_ZEROS_PADDING :  ONE_AND_ZEROS_PADDING to use 0x80 instead 0x01 as padding
DEFAULT_PADDING : DEFAULT_PADDING means PKCS_PADDING 
  if c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0 (e.g. ECB or CBC mode), otherwise NO_PADDING (OFB, CFB, CTR, CBC-CTS modes)
 
 
예제, 필요한 헤더파일 (SEED, AES, DES 사용시..)
#include <iostream>
using namespace std;

//#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1   

// Crypto++ Includes
#include "cryptlib.h"
#include "Base64.h"
#include "aes.h"        
#include "seed.h"
#include "des.h"
#include "modes.h"      
#include "filters.h"    

#pragma comment(lib, "cryptlib")  

template <class TyMode>
std::string Encrypt(TyMode &Encryptor, const std::string &PlainText)
{
	std::string EncodedText;

	try {
		CryptoPP::StringSource(PlainText, true,
			new CryptoPP::StreamTransformationFilter(Encryptor,
				new CryptoPP::Base64Encoder(
					new CryptoPP::StringSink(EncodedText), false
					), CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING
				)
			);
	}
	catch (...) {}

	return EncodedText;
}

template <class TyMode>
std::string Decrypt(TyMode &Decryptor, const std::string &EncodedText)
{
	std::string RecoveredText;

	try {
		CryptoPP::StringSource(EncodedText, true,
			new CryptoPP::Base64Decoder(
				new CryptoPP::StreamTransformationFilter(Decryptor,
					new CryptoPP::StringSink(RecoveredText),
					CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING
					)
				)
			);
	}
	catch (...) {}

	return RecoveredText;
}

template <class Ty>
std::string CBC_Encrypt(byte *KEY, byte *IV, const std::string &PlainText)
{
	typename CryptoPP::CBC_Mode<Ty>::Encryption Encryptor(KEY, Ty::DEFAULT_KEYLENGTH, IV);
	return Encrypt(Encryptor, PlainText);
}


template <class Ty>
std::string CBC_Decrypt(byte *KEY, byte *IV, const std::string &PlainText)
{
	typename CryptoPP::CBC_Mode<Ty>::Decryption Decryptor(KEY, Ty::DEFAULT_KEYLENGTH, IV);
	return Decrypt(Decryptor, PlainText);
}

template <class Ty>
std::string ECB_Encrypt(byte *KEY, const std::string &PlainText)
{
	typename CryptoPP::ECB_Mode<Ty>::Encryption Encryptor(KEY, Ty::DEFAULT_KEYLENGTH);
	return Encrypt(Encryptor, PlainText);
}


template <class Ty>
std::string ECB_Decrypt(byte *KEY, const std::string &PlainText)
{
	typename CryptoPP::ECB_Mode<Ty>::Decryption Decryptor(KEY, Ty::DEFAULT_KEYLENGTH);
	return Decrypt(Decryptor, PlainText);
}


template <class CryptoType>
void Test()
{
	using namespace std;

	const std::string sText = "Plain Text";
	std::string sEnc, sDec;

	byte KEY[CryptoType::DEFAULT_KEYLENGTH] = { 0, };
	byte IV[CryptoType::BLOCKSIZE] = { 0x01, };

	// CBC 모드
	sEnc = CBC_Encrypt<CryptoType>(KEY, IV, sText);
	sDec = CBC_Decrypt<CryptoType>(KEY, IV, sEnc);

	cout << CryptoType::StaticAlgorithmName() << " : " << "CBC_MODE" << endl;
	cout << sText << "\n -> " << sEnc << "\n -> " << sDec << endl;


	// ECB 모드
	sEnc = ECB_Encrypt<CryptoType>(KEY, sText);
	sDec = ECB_Decrypt<CryptoType>(KEY, sEnc);

	cout << CryptoType::StaticAlgorithmName() << " : " << "ECB_MODE" << endl;
	cout << sText << "\n -> " << sEnc << "\n -> " << sDec << endl;
	cout << endl;
}


int main()
{
	using namespace std;

	// SEED 
	Test<CryptoPP::SEED>();

	// AES 
	Test<CryptoPP::AES>();

	// DES 
	Test<CryptoPP::DES>();

	return 0;
}
  
 

 


 패키지 활성화   JIT 활성화  멤버변수 상태 유지  전역변수 상태
 1. 서버 응용 프로그램  활성  유지 않함  유지 (활성화 개체 단위)
 2. 서버 응용 프로그램  비 활성  유지  유지 (활성화 개체 단위)
 3. 라이브러리 응용 프로그램  활성  유지 않함  유지 (세션 단위)
 4. 라이브러리 응용 프로그램  비 활성  유지  유지 (세션 단위)

* JIT 활성화가 있는경우 Method 단위로 m_spObjectContext->SetComplete() 를 호출 하여 테스트
* 풀링의 세팅의 경우 위의 결과와 틀리게 멤버변수의 상태가 달라 질 수 있음 
* CreateObject 이후 Nothing 까지의 상태 


내용 
- JIT 활성화인 경우 Method 단위로 클래스의 생성자 및 소멸자 호출 
- 풀링 설정의 경우 패키지가 시작할때 풀링된 구성요소 만큼 생성자를 호출하여 인스턴스 생성해 놓음 
- 라이브러리 응용 프로그램의 경우 인프로세스로 실행 되므로 전역변수값은 세션별로만 유지함
- regsvr32 로 등록되어 있는 컴포넌트랑 같은 효과를 내기 위해서는 "라이브러리 응용 프로그램, JIT 비활성화"로 운영

결론
내가 만들지 않은 컴포넌트의 경우 내부적으로 개체의 상태값 유지를 위해서,
멤버변수를 사용했는지, 지역 변수를 사용했는지 알 수 없기 때문에 regsvr32 로 등록하여 사용 하는것으로 권장

허나 COM+에 등록하여 사용 하려면 위의 내용 참고



'Dev > Windows' 카테고리의 다른 글

MS MTC 서비스 설정  (0) 2012.04.04
.svn 폴더 삭제  (0) 2011.03.25
Redmine 세팅  (0) 2009.09.12
ATL Com Project VC++ 6 에서 VC++ 8 변환(업그레이드)  (0) 2009.03.27
유니코드(UNICODE), C++  (0) 2008.10.16
BitNami Redmine Stack 받기: http://bitnami.org/stack/redmine


한글을 문제 없이 사용위해 DB를 UTF-8 로 설정 하기 위한 작업 + 기타 등등..

1. MySql 설정 변경 
-> \BitNami Redmine Stack\mysql\my.ini 

[client] 
default-character-set=utf8

[mysqld] 
character-set-client-handshake = FALSE 
init_connect=SET collation_connection = utf8_general_ci 
init_connect=SET NAMES utf8 
default-character-set=utf8 
character-set-server=utf8 
collation-server=utf8_general_ci

[mysql] 
default-character-set=utf8


2. MySql 설정 확인
-> \BitNami Redmine Stack\mysql\bin\mysql -uroot -p 

mysql> show variables like 'c%';
mysql> status;


3. 기존 bitnami_redmine DB, UTF-8로 다시 만들기 

mysql> drop database bitnami_redmine ;
mysql> CREATE DATABASE bitnami_redmine DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;


4. 어플리케이션 DB 접속 encoding 수정 
-> \BitNami Redmine Stack\apps\redmine\config\database.yml

production:
  adapter: mysql
  database: redmine_production
  host: localhost
  username: bitnami
  password: bitnami 
  port: 3306
  encoding: utf8


5. 생성된 bitnami_redmine DB 설정 초기화 작업 

// 환경변수 세팅 
\BitNami Redmine Stack\scripts>setenv.bat
// DB Migration
\BitNami Redmine Stack\apps\redmine>rake db:migrate RAILS_ENV="production"


6. SMTP 설정 : 로컬 SMTP 서버 이용 
email.yml 수정 (기존 파일이 없을 경우 email.yml.example 를 복사후 rename)
->\BitNami Redmine Stack\apps\redmine\config\email.yml

production:
  delivery_method: :smtp
  smtp_settings:
    address: localhost
    port: 25
    domain:   
    authentication:
    user_name: 
    password: 
  

7. "일감" -> "이슈" 로 Replace (일감이란 단어의 어감이 좋지 않아서;;)
-> \BitNami Redmine Stack\apps\redmine\lang\ko.yml


출처 : 

1. 효과적인 Backend System 구현 
  - IE + ActiveX 환경에서의 진화 

2. Prototype.js vs jQuery
  - Prototype.js를 쓰고 있는데 도통 jQuery 인기다. 
  - Prototype.js을 열심히 쓸것이냐? 아니면 jQuery 로의 전환을 시도 할것인가 
  - 팔랑팔랑 ㅎㅎ

3. 모바일 서비스 
  - 예약/예매 시스템의 모바일 서비스 최적화 

4. UX (User eXperience)
  - 기술집약 혹은 복잡한 서비스들의 UX 개선 방향 
  - 기획 단계에서의 UX 적용 방법 

5. designed, specified, implemented, tested, documented and shipped

6. 업무프로세스 + 개발프로세스를 쉽게 작성, 표현 할 수 있는 툴, 방법 찾기 

7. Visual Studio 2005 에서 2008 버전으로 넘어갈 시기

8. 아이폰

9. 트위터에서의 예약/예매 서비스




계속 생각만하고 있음.........


'일상' 카테고리의 다른 글

twitter 잡담  (0) 2009.08.15
근황, 단상 - 2009.08.08  (0) 2009.08.08
생각의 정리..  (0) 2008.12.17
회의를 좋아하는 매니저의 특징  (0) 2008.09.17
팀장 딜레마..  (0) 2007.07.02
1.
티맥스 OS 사태(?)를 계기로 트위터를 시작했다.
여기저기 돌아 댕기면서 부담없이 Follow를 하고 의견, 정보를 공유하는 것이 왠지 메신저의 내용을 rss 구독 하는 느낌이 든다
비슷한 서비스인 미투데이 경우는 몇번이고 시도 해봤지만 어디서 부터 시작해야 될지 모른다는 느낌에 손이 가질 않는다.


2.
좀 더 편하게 사용할 요량으로 클라이언트를 몇개 사용해 봤는데, 왠지 딱 이거다 하는 툴은 없어보인다.
대부분은 Adobe AIR 플랫폼을 개발이 되어 있고 몇몇은 .NET 환경도 있는듯 하다.

Adobe AIR의 경우 트위터 어플을 통해서 사람들한테 가장 많이 사용되어 지지 않았나 생각이 든다.


지금까지 사용해본 몇개의 어플의 개인적인 불편한 점은..

TweetDeck 은 가장 많이 사용하는 어플이긴한데, 화면의 크기 조정이 안된고 글이 약간 긴 경우 마우스를 긁어서 내려 봐야하는 수고스러움이 있다.

Twhirl 는 그나마 맘에 든 어플이지만, 한글입력시에 백스페이스 키로 지우다 보면 초성이 잘려서 커서 뒤로 가는 경우가 생긴다.
한글 입력의 경우는 Twhirl 뿐만 아니라 AIR 플랫폼으로 개발된 어플들은 대부분 그러한듯 하다.

Seesmic 이나 DestroyTwitter 기능상 불편한 부분이 있어서 설치하고 얼마 못가 지워 버렸다.

Firefox 의 부가기능인 TwiterFox의 경우 간단하게 보기엔 깔끔한 인터페이스지만,
역시 Follow 수가 많아 지고 글이 넘치기 시작하면 관리가 불가능 해진다.

그리고 그리즈몽키로 스크립트를 이용해서 사이트를 보기 편하게 만드는 pbtweet 이란것도 있다


3.
클라이언트를 한번 만들어 볼까 생각을 해봤는데 역시 어플의 경우는 UI 의 표현 부분 때문에 많은 시간이 들어 갈것 같다.
AIR 나 WFP 같은 플랫폼을 만드는 이유도 그 이유 때문 일것이고..

그래서 pbtweet 과 같이 html + javascript 로 개발하는것이 좋을것 같고, 추가적으로 읽음 표시, 마지막 읽은 시간 관리 등이 추가 되면 좋지 않을까 생각한다..


언제 시간이 되면 한번 해봐야지.. 라고 생각하지만 그때쯤 되면 더 좋은 어플이 나오지 않을까?? 흐흐..

'일상' 카테고리의 다른 글

요즘 IT 관심사 - 2009.09.02  (0) 2009.09.02
근황, 단상 - 2009.08.08  (0) 2009.08.08
생각의 정리..  (0) 2008.12.17
회의를 좋아하는 매니저의 특징  (0) 2008.09.17
팀장 딜레마..  (0) 2007.07.02

- 기존에 TextWriter 객체에 Serialize 하니 XML Declaration 부분에 UTF-16으로 고정 되어서 MemoryStream 로 교체
- MemoryStream는 XML Declaration 부분을 표시 하지 않음


using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

// 구현
protected string SerializeToXML<T>(T t)
{
    string strXml = "";
    XmlSerializer xs = new XmlSerializer(typeof(T));

    try
    {
        using (MemoryStream ms = new MemoryStream())
        {
            xs.Serialize(ms, t);
            strXml = Encoding.UTF8.GetString(ms.ToArray());
        }

    }
    catch (Exception) { }

    return strXml;
}

'Dev > .NET' 카테고리의 다른 글

LUCENE.NET 검색엔진  (0) 2013.01.02
C# Web Service -> REST  (0) 2009.08.09
Integrating WCF Services with COM+  (0) 2008.09.03
Interop 응용 프로그램 배포  (0) 2007.10.05
RCW, CCW  (0) 2007.10.04
Web Service(WSDL), REST 어떤 방식으로 서비스를 만들면 좋을것인가 고민을 한적이있다.

그런데 왜 난 꼭 REST 방식을 웹페이지로 따로 만들어야 된다고 생각을 했을까?
그냥 아래와 같이 Web Service에 대해서 GET, POST 방식을 같이 노출하면 같이 사용할 수 있는데..


Web Service 의 인터페이스 메쏘드의 Input 파라미터에 대해서 Complex Type을 쓰지 않고 기본 타입을 쓰고,
web.config 에 아래와 같이 GET, POST 방식을 노출 해주면 끝.
<configuration>
<system.web>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
</system.web>
</configuration>
하지만 Basic Type 을 쓰면 Strong한 타입 체킹을 할 수 없다는 단점이 있긴하다..

'Dev > .NET' 카테고리의 다른 글

LUCENE.NET 검색엔진  (0) 2013.01.02
SerializeToXML - C#  (0) 2009.08.10
Integrating WCF Services with COM+  (0) 2008.09.03
Interop 응용 프로그램 배포  (0) 2007.10.05
RCW, CCW  (0) 2007.10.04

1. 서버의 "예약된 작업" 을 웹으로 모니터링 하기 위한  페이지를 만들기

우선 관련 API 를 조사하던 도중 아래의 것이 나왔다.

http://msdn.microsoft.com/en-us/library/aa383614%28VS.85%29.aspx

Developer Audience

The Task Scheduler provides APIs for the following developers:

  • Task Scheduler 1.0: Interfaces are provided for C++ development.
  • Task Scheduler 2.0: Interfaces and objects are provided for C++ and scripting development respectively.

Run-Time Requirements

The Task Scheduler requires the following operating systems.

  • Task Scheduler 1.0: Client requires Windows Vista, Windows XP, Windows 2000 Professional, Windows Me, or Windows 98. Server requires Windows Server 2008, Windows Server 2003 or Windows 2000 Server.
  • Task Scheduler 2.0: Client requires Windows Vista. Server requires Windows Server 2008.

그런데 웹페이지에서 사용할 것이라 컴포넌트 형태의 API가 필요 했는데 위에 나와있듯이,
Task Scheduler 2.0 인터페이스 에서만 "scripting development" 환경이 제공되는데 OS 지원이 Vista, Windows Server 2008 이다.

2003 서버에 적용할 것이라 이것은 사용못할 것이고..

그렇다고 C++ 인터페이스로 제공된것을 다시 COM으로 만들어서 등록하고 사용하자니 여간 귀찮은게 아니다.
그런던중 .NET 의 라이브러리 형태로 Task Scheduler 를 래핑한 모듈을 발견 !!

http://www.codeproject.com/KB/cs/tsnewlib.aspx?fid=4062&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=226&select=1917304

멋지다.. ^^b

콘솔 어플리케이션으로 테스트 해보니 잘 되어 웹어플리케이션으로 실행하니 권한에러 발생..
어짜피 관리용이니 관리자용 계정으로 IIS App Pool 을 만들어 세팅하고 실행하니 잘된다.

데이터를 List<> 에 넣고 XML Serialize 해서 클라이언트에서 AJAX 로 호출해서 화면 완성



2. C++0x 의 기능들을 이것저것 테스트 해보는데, 아직까지 어느정도 구현되어 있는 컴파일러는 없는듯..
g++은 Lambda expressions and closures 가 안되고 vc++ 2010은 Initializer Lists 안되고..

그나저다 C++에 Lambda가 추가가 됬으니 boost::Lambda 는 이제 계륵이 되는것인가??



3. twitter 시작.. 언제까지 할지는 모르겠지만.. ;;
 
http://twitter.com/cdecl
http://twitterfox.net/


'일상' 카테고리의 다른 글

요즘 IT 관심사 - 2009.09.02  (0) 2009.09.02
twitter 잡담  (0) 2009.08.15
생각의 정리..  (0) 2008.12.17
회의를 좋아하는 매니저의 특징  (0) 2008.09.17
팀장 딜레마..  (0) 2007.07.02
C++0x RValue Reference 라는것이 추가 되었다.


RValue Reference는  Move semantics와 Perfect forwarding 이라는 두가지 기능을 가진다.


1. Move semantics

기존 부터 있던 Reference는 LValue Reference 라고 불린다.

int n = 10;
int &r = n;  // LValue Reference
int *p = &n;  // 포인터 참조 방식
cout << r << " " << *p << endl;

C++의 참조는 내부적으로 포인터를 사용하여 참조를 하게 되지만 사용함에 있어 보다 우아하게(?) 사용을 할 수 있다는 장점이 있다.


반면 RValue Reference는 아래와 같이 사용한다.

int n = 10;
int &&r =n; // 그런데 기존 참조랑 머가 틀리냐??

int, long 등의 기본 타입과 기존 클래스의 복사생성자, 대입연산자에 대해서는 RValue Reference 참조는 기존 Value Reference와 똑같이 동작을 한다.

하지만 RValue Reference는 객체(변수)의 주소를 참조하는 기존의 LValue Reference와 틀리게,
RValue Reference 로 겹지정한 복사생성자 및 대입연산자를 따로 구현, 그리고 그것을 의도적으로 호출하게 할 수 있다.

그리고 그 RValue Reference 로 겹지정한 복사생성자 및 대입연산자에는,
임시객체애 대해서 복사가 아닌  메모리를 이동 (Move) 하는 방법으로 임시 객체의 생성및 소멸에 대한 비용을 줄이는 구현이가능해 진것이다.

소유권 이전 기법을 사용하는 auto_ptr 처럼..



class Item
{
  public:
    Item() : p(new char[100]) {}
    Item(const Item &t) : p(new char[100]) {  memcpy(p, t.p);  } // 복사생성자
    Item(Item &&t) : p(t.p) { t.p = NULL;  } // Move 생성자

    // Item& operator=(const Item &t) { return *this; } // 대입연산자
    // Item& operator=(Item &&t) { return *this; } // Move 대입 연산자
    // ...
   ~Item() { if (p) delete p; }
  
  private:
    char *p;
};

Item&& foo()
{
  Item item;
  // ...
  return item;
}

int main()
{
  Item item;
  Item t = item; // 복사생성자 호출
  Item &r = item; // 참조

  Item &&rr = Item; // 참조
  Item &&mv = std::move(item);  // Move 생성자
  Item &&mvt = foo(); // // Move 생성자
}

위의 코드와 같이 foo() 함수에서 RValue Reference로 리턴을 하게 되면,
Item 객체의 RValue Reference 버전의 Move 생성자가 호출되고
Move 생성자에서 내부 멤버인 포인터의 소유권을 이전하여 임시객체에 대해서 필요 없는 생성-소멸의 과정을 거치지 않게끔 할 수 있는것이다.

그리고 강제로 Move 생성자, Move 대입 연산자를 호출 하기 위해서 std::move() 함수를  이용 할 수도 있다.


C++0x 의 STL에는 RValue Reference 의 코드가 적용 되어 있어 사용하는 것 만으로도 성능 효과를 볼 수가 있다고 한다.
대략 다음과 같은 코드..

std::string s = "s";
std::string str;
str = s + "t" + "r" + "i" + "g";  // 임시객체 (RValue Reference) 사용



2. Perfect forwarding

template 의 내부 함수가 참조 및 상수의 값을 파라미터로 받을 경우 관련되서 여러 개의 버전 구현을 해야하는 문제를,
RValue Reference의 문법으로 하나로 처리 하는 내용.
(자세한 내용은 아래링크 -_-; )



참고 : http://blogs.msdn.com/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx


'Dev > C++' 카테고리의 다른 글

boost::asio 클라이언트 소켓 (timeout 기능)  (0) 2010.10.14
이미지 변환 모듈 (모바일용, GDI+)  (0) 2010.06.22
C++0x Lambda  (0) 2009.05.20
C++0x 지원 컴파일러 목록  (0) 2009.05.20
C++ Refactoring  (0) 2009.04.14
아래 링크의 글 중 Herb Sutter 의 Lambda 예제 및 설명에 관한 리플..
http://herbsutter.wordpress.com/2008/03/29/trip-report-februarymarch-2008-iso-c-standards-meeting/

[]와 []안에 들어가는 내용에 대해서 명쾌하게 설명을..




Herb Sutter

Re binders: Okay, I give! I’ll use a better example next time.

(no name) asked: "How are local variables captured?" You have to specify whether it’s by copy or by reference. So this example is illegal because it tries to use a local variable:

    int numWidgets = 0;
    for_each( v.begin(), v.end(), []( Widget& w )
    {
        ++numWidgets;  // error, numWidgets is not in scope
    } );

If you want to update numWidgets directly, capture it by reference:

    for_each( v.begin(), v.end(), [&numWidgets]( Widget& w )
    {
        ++numWidgets;  // increments original numWidgets
    } );
    // numWidgets == v.size() here

Or use the shorthand [&] to take all captured variables implicitly by reference:

    for_each( v.begin(), v.end(), [&]( Widget& w )
    {
        ++numWidgets;  // increments original numWidgets
    } );
    // numWidgets == v.size() here

What if you want a local copy? You say to pass it by value, but for safety reasons the current proposal says you get a read-only copy that you can’t modify:

    for_each( v.begin(), v.end(), [numWidgets]( Widget& w )
    {
        int i = numWidgets; // ok
        ++i;
        // "++numWidgets;" would be an error
    } );
    // numWidgets == 0 here

Or use the shorthand [=] to take all captured variables implicitly by copy:

    for_each( v.begin(), v.end(), [=]( Widget& w )
    {
        int i = numWidgets; // ok
        ++i;
        // "++numWidgets;" would be an error
    } );
    // numWidgets == 0 here

Similarly, for the question: "What will happen in the following case:"

    int flag = 0;
    mypool.run( [] { flag = 1; } );
    cout << flag << endl;

The answer is that the code is illegal, you have to say whether you capture flag by value or by reference, which can be as simple as replacing [] with [=] or [&]. And if you capture by value, you get a read-only copy so you couldn’t assign to it.


'Dev > C++' 카테고리의 다른 글

이미지 변환 모듈 (모바일용, GDI+)  (0) 2010.06.22
C++0x, RValue Reference  (0) 2009.05.27
C++0x 지원 컴파일러 목록  (0) 2009.05.20
C++ Refactoring  (0) 2009.04.14
An Overview of the Coming C++ (C++0x) Standard  (0) 2008.12.29

'Dev > C++' 카테고리의 다른 글

C++0x, RValue Reference  (0) 2009.05.27
C++0x Lambda  (0) 2009.05.20
C++ Refactoring  (0) 2009.04.14
An Overview of the Coming C++ (C++0x) Standard  (0) 2008.12.29
asio C++ library  (0) 2008.08.22

+ Recent posts