detach 함수는 thread 오브젝트에 연결된 스레드를 떼어냅니다.

그래서 detach 이후에는 thread 오브젝트로 스레드를 제어할 수 없습니다. 그러나 detach를 호출했다고 해서 관련된 스레드가 종료 되는 것이 아닙니다. thread 오브젝트와 스레드의 연결이 끊어지는 것입니다.

 

 

< 예제. 5 >

#include <thread>

#include <iostream>

 

int main()

{

           int nThreadRunCount = 0;

           std::thread Thread = std::thread( [&] ()

                                {

                                           for( int i = 0; i < 10; ++i )

                                          {

                                          ++nThreadRunCount;

                                         

                                          std::cout << "Thread1 ID : " << Thread.get_id() << std::endl;

                                          }

                              } );

 

           while( nThreadRunCount < 3 )

           {

           }

 

           Thread.detach();

 

           //Thread.join();

 

           getchar();

           return 0;

}

 

< 실행 결과 >


 

<예제. 5>의 결과를 보면 detach 이후 스레드 id가 초기화 됨을 알 수 있습니다. 그리고 위 예제에서 join() 메소드를 주석 처리하고 있는데 만약 주석을 풀면 아래와 같은 에러가 발생합니다.



 

이렇게 thread 오브젝트가 스레드를 가지지 않는데 join 함수를 호출하면 에러가 발생하는 것을 막기 위해서는 joinable 함수를 사용합니다. joinable 함수를 호출하여 반환 값이 true인 경우에만  join 함수를 호출하면 위와 같은 에러를 막을 수 있습니다.

 

< 예제. 6 >

#include <thread>

#include <iostream>

#include <mutex>

 

int main()

{

           std::mutex mtx_lock;

 

           int nThreadRunCount = 0;

           std::thread Thread = std::thread( [&] ()

                                {

                                for( int i = 0; i < 10; ++i )

                                {

                          ++nThreadRunCount;

                                                               

                                  mtx_lock.lock();

                                  std::cout << "Thread1 ID : " << Thread.get_id() << std::endl;

                                  mtx_lock.unlock();

                                }

                          } );

 

           while( nThreadRunCount < 3 )

           {

                     mtx_lock.lock();

                     std::cout << "Thread Is Joinable : " << Thread.joinable() << std::endl;

                     mtx_lock.unlock();

           }

 

           Thread.detach();

 

           std::cout << "Thread Is Joinable : " << Thread.joinable() << std::endl;

 

           getchar();

           return 0;

}

 

< 실행 결과 3>

 

 

저작자 표시
신고
by 흥배 2013.05.03 08:00

C++11의 새로운 기능 중 'SCARY iterator' 라는 것이 있습니다. 단순히 한국말로 바꾸면 '무서운 반복자' 라고 할 수 있는데 사실 무섭지는 않습니다.^^;

 

SCARY iterator에 대해서 아주 간단하게 말하면 컨테이너를 선언할 때 템플릿에 들어가는 데이터 타입만 같다면 비교 함수나 메모리 할당자가 서로 달라도 같은 반복자를 사용할 수 있게 해줍니다(만약 메모리 할당자의 차이에 의해서 이상한 결과가 나올 수도 있어서 무서운 이라는 단어를 사용하지 않았나 생각합니다);

 

SCARY iterator가 구현 되기 전에는 아래와 같이 데이터 타입은 같으나 비교 함수가 서로 다른


std::set< int, std::less<int> > map1;

std::set< int, std::greater<int> > map2;


에서 map1 map2의 반복자는 서로 같지 않습니다. 분명히 int라는 같은 타입을 사용해서 같은 반복자를 사용해도 문제 없

을 거라고 생각되지만 비교 함수가 서로 틀려서 반복자는 서로 다른 타입으로 취급합니다. 그래서 아래의 코드는 컴파일 에러가 발생합니다.

 

std::set<int, std::less<int>>::iterator Iter = b.begin();

 

그러나 C++11SCARY iterator가 구현된 VC11에서는 위의 코드는 전혀 에러가 발생하지 않습니다.

 

VC11처럼 SCARY iterator가 구현된 컴파일러에서는 컨테이너의 데이터 타입만 같다면 같은 반복자를 사용할 수 있게 되었습니다.

 

 


 

참고 : http://blogs.wankuma.com/episteme/archive/2013/01/11/311581.aspx

 

저작자 표시
신고
by 흥배 2013.03.21 08:00

C#이나 Java와 다르게 C++(물론 C)은 동적 메모리 할당과 해제에 신경을 써야 합니다. 그리고 높은 성능까지 원한다면 메모리 관리자를 직접 만들어서 동적 할당과 해제를 직접 관리하여 실시간으로 동적 할당이 일어나지 않도록 해야 합니다.

 

그러나 범용적인 목적을 가지 메모리 관리자는 만들기가 쉽지 않고 특히 멀티 스레드 환경에서 사용해야 하는 경우는 잘못하면 오히려 더 느려질 수 있습니다.

 

현재 Windows에서는 LFH를 사용하여 이전보다 동적 할당과 해제에 대한 성능을 개선했습니다. 그러나 이것보다 더 성능을 좋게 하는 방법이 있습니다.

그것은 VC++10에서 추가된 라이브러리인 Concurrency Runtime에서 제공하는 메모리 관리자를 사용하는 것입니다.

메모리 할당을 할 때는 Concurrency::Alloc, 메모리 해제를 할 때는 Concurrency::Free 를 사용합니다.

 

MSDN에 있는 샘플 중 new/delete, malloc/free와 비교한 것을 보면 new/delete에 비해서는 3배 정도 성능이 좋습니다.

http://msdn.microsoft.com/en-us/library/dd998050.aspx

 

 

저작자 표시
신고
by 흥배 2013.01.29 22:03

range base for는 다 좋은데 조금 아쉬운 부분이 있습니다.

그것은 앞에서 뒤로 순차적으로만 접근이 된다는 것입니다.

때로는 뒤에서부터 시작해야 할 때가 있습니다.

 

이때는 일반적인 방법으로는 안되고 boost 라이브러리의 도움을 받으면 할 수 있습니다.

boost 라이브러리의 boost::adaptors::reverse 를 사용합니다.

 

< 예제. 4 >

#include <iostream>

#include <boost/range/adaptors.hpp>

 

int main()

{

           int NumberList[] = { 1, 2, 3 };

 

           for (auto i : boost::adaptors::reverse(NumberList))

           {

                     std::cout << i << "  ";

           }

 

           std::cout << std::endl << std::endl;

 

 

 

           std::vector<int> vecNumberList;

           vecNumberList.push_back( 1 );

           vecNumberList.push_back( 2 );

           vecNumberList.push_back( 3 );

 

           for (auto i : boost::adaptors::reverse(vecNumberList))

           {

                     std::cout << i << "  ";

           }

 

           std::cout << std::endl;

 

           return 0;

}

 

< 실행 결과 >


저작자 표시
신고
by 흥배 2012.10.15 09:00

range base for에서 데이터셋의 요소를 변경할 수 있을까요?

정답은 있을 수도 있고, 없을 수도 있습니다.

 

앞 선 예제 코드에서는

for( auto i : NumberList )

이런 식으로 사용했는데 이런 경우 i의 값을 for 문 안에서 변경 할 수 있지만 for 문을 나오면 NumberList의 요소에는 적용되지 않습니다.

 

만약 요소의 값을 변경하고 싶다면 참조를 사용하면 됩니다.

for( auto &i : NumberList )

이런 식으로 하면 for 문을 나와도 NumberList의 요소는 변경이 적용되어 있습니다.

 

그런데 만약 for 문에서 요소 값을 변경하지 못하도록 하려면 const를 사용합니다.

for( auto const i : NumberList )

 

for 문에서 데이터셋 요소를 접근할 때는 임시 변수를 만들기 때문에 이 비용을 줄이고 싶다면 참조를 사용하면 좋습니다.

또 만약 요소의 값을 변경하지 못하도록 하고 싶다면 const 참조를 사용합니다.

for( auto const &i : NumberList )

 


< 예제. 3 >

#include <iostream>

#include <vector>

 

int main()

{

           std::vector<int> NumberList;

           NumberList.push_back( 1 );

           NumberList.push_back( 2 );

           NumberList.push_back( 3 );

          

           for( auto i : NumberList )

           {

                     std::cout << i << " * 10 : ";

 

                     i *= 10;

                     std::cout << i << std::endl;

           }

 

           for( auto i : NumberList )

           {

                     std::cout << i << "  ";

           }

          

           std::cout << std::endl << std::endl;

 

 

           for( auto &i : NumberList )

           {

                     std::cout << i << " * 10 : ";

 

                     i *= 10;

                     std::cout << i << std::endl;

           }

 

           for( auto i : NumberList )

           {

                     std::cout << i << "  ";

           }

 

           std::cout << std::endl;

 

           return 0;

}

 

< 실행 결과 >




저작자 표시
신고
by 흥배 2012.09.26 01:07

너무 당연한 것이지만 range base for에는 배열 뿐만이 아닌 STL의 컨테이너들도 사용할 수 있습니다.

아래 예제를 통해서 STL 컨테이너를 range base for문에서 어떻게 사용하는지 보겠습니다.

 

< 예제. 2 >

#include <iostream>

#include <vector>

#include <unordered_map>

#include <string>

 

int main()

{

           std::cout << "range base for - vector" << std::endl;

 

           std::vector<int> NumberList;

           NumberList.push_back( 1 );

           NumberList.push_back( 2 );

           NumberList.push_back( 3 );

          

           for( auto i : NumberList )

           {

                     std::cout << i << std::endl;

           }

           std::cout << std::endl;

 

 

 

           std::cout << "range base for - unordered_map" << std::endl;

 

           std::unordered_map<int, std::string> NumString;

           NumString.insert( std::make_pair<int, std::string>(1, "1") );

           NumString.insert( std::make_pair<int, std::string>(2, "2") );

           NumString.insert( std::make_pair<int, std::string>(3, "3") );

 

           for( auto i : NumString )

           {

                     std::cout << "key : " << i.first << ", value : " << i.second << std::endl;

           }

 

           std::cout << std::endl;

 

           return 0;

}

 

< 실행 결과 >


 

 

range base for문은 기본적으로 STL의 이터레이터를 지원하는 컨테이너라면 문제 없이 사용할 수 있습니다. 그러므로 프로그래머가 자신만의 컨테이너를 만든다면 STL에서 정의한 이터레이터의 기능을 구현하면 range base for 문을 사용할 수 있습니다.

 

이전에는 STL 컨테이너의 모든 요소를 반복문에서 사용할 때  for_each를 사용했는데 사용하기 위해서 준비해야 할 것이 많았는데 VC10에서 lambda 덕분에 쉬워졌습니다. 그러나 range base for 문과 비교해보면 for_each+lambda 보다는 range base for 문이 더 사용하기 편한 것을 알 수 있습니다.

 

이제 VC11부터 for 반복문은 꼭 range base for를 사용하기 바랍니다^^

저작자 표시
신고
by 흥배 2012.09.21 13:01

앞에까지는 STL의 알고리즘에 추가된 것들을 다루었는데 이번에는 컨테이너 하나를 소개하겠습니다사실 이 컨테이너는 저도 얼마 전까지만 하더라도 새로 추가 된지 몰랐습니다.^^;

 

새로 추가된 컨테이너의 이름은 forward_list입니다.

이름을 들어보니 대충 어떤 컨테이너인지 감이 오시죠?^^ 네 이 컨테이너는 기존의 list 컨테이너와 비슷한 종류의 컨테이너입니다.

 

 

forward_list를 만든 이유

표준 라이브러리(STL)에는 이미 리스트(std::list) 라이브러리가 있습니다이것은 쌍 방향 리스트입니다. list는 사용하기는 편하지만 사용 메모리나 처리 속도에 조금 아쉬운 점이 있습니다또 대 부분의 상황에서 쌍 방향 리스트가 필요한 경우보다는 단 방향 리스트만으로 충분한 경우가 자주 있습니다이런 이유로C++0x에서는 단 방향 리스트를 추가하기로 했습니다.

 

 

forward_list의 설계 방침

1. 특별한 이유가 없다면 forward_list는 기존의 list의 설계에 맞춘다.

2. 설계 상의 선택 기가 여러 개인 경우 성능(속도와 사이즈)을 최우선 한다(C의 구조체로 구현하는 경우와 비교하여 Zero Overhead로 한다).

3. std::list insert erase를 forward_list에서도 제공할 수 있지만 구현이 복잡해지고 성능 측면에서 좋지 않으므로 제공하지 않는다.

4. 다른 STL의 컨테이너들에 있는 size 함수를 제공하지 않는다이유는 요소 수를 보존하는 멤버를가지고 있으면 C언어에서 구현한 것과 비교해서 불필요한 메모리를 사용한다. 만약 이런 멤버를 가지고 있지 않으면서 size 함수를 지원하면 호출할 때마다 모든 요소를 세어야 하므로 계산량이 O(N)이 된다(그런데 유저는 다른 컨테이너와 같이 size의 계산량이 작을 것이라고 생각할 수 있다). 또 이미 unordered와 같은 연상 컨테이너도 기존의 요소를 만족하지 않고 있다.

  

 

STL list 컨테이너와 다른 점

forward_list는 기존의 list와 아래와 같은 점이 다릅니다.

1. forward_list는 단 방향 리스트(singly-linked-list)이다각 요소는 그 다음 요소를 가리키는 포인터를 하나만 가지고 있다(list은 양 방향 리스트).

2. (단 방향 리스트이므로) list에 비해서 메모리를 작게 사용한다이것은 각 요소의 메모리만이 아닌 컨테이너 그 자체의 사이즈도 작다. int 형에 대해서 list 12바이트라면 forward_list 8바이트이다(64비트에서는 각각 24, 16).

3. list에 비해 삽입/삭제 속도가 더 빠르지만 그 차이는 크지는 않다

4. 한 방향으로만 이동할 수 있다.

5. 삽입과 삭제는 지정한 요소의 다음 요소만 가능하다.

 

 

forward_list의 멤버 리스트

기능

멤버

대입

assign

반복자

befor_begin

 

cbefore_begin

 

begin

 

end

 

cbegin

 

cend

비었는지 조사

empty

현재 크기(size)

지원 안함

사이즈 변경

resize

모두 삭제

clear

선두에 추가

push_front

선두 요소 삭제

pop_front

선두 요소 참조

front

삽입

insert_after

삭제

erase_after

조건 삭제

remove

 

remove_if

중복 요소 삭제

unique

교환

swap

병합

merge

정렬

sort

반전

reverse

 


STL의 컨테이너를 사용해보았다면 forward_list라고 해서 딱히 어려운 부분은 없습니다다만 forward_list이 단 방향 리스트라는 것과 다른 컨테이너에서는 지원하는 기능이 일부 없다는 것을 잘 숙지해야 합니다.

 

필요한 헤더 파일

forward_list는 이름과 같은 ‘forward_list’라는 헤더 파일을 포함해야 합니다.

#include <forward_list>

 

 

[예제] forward_list를 사용하여 요소 추가순회삭제하기

#include "stdafx.h"

#include <iostream>

#include <forward_list>

 

using namespace std;

 

 

int main()

{

           forward_list< int > flist;

 

 

           cout << "flist에 추가한 요소들 출력" << endl;

           // 추가하기

           auto iter = flist.before_begin();

           for( int i = 0; i < 5; ++i )

           {

                     iter = flist.insert_after( iter, i );

           }

                    

           // 순회

           for( iter = flist.begin(); iter != flist.end(); ++iter )

           {

                     cout << *iter << endl;

           }

 

           cout << endl;

           cout << "flist의 요소들 중 일부를 삭제한 후 남은 요소들 출력" << endl;

           // 순회 하면서 일부 요소 삭제

           auto prev_iter = flist.before_begin();

           iter = flist.begin();

           while( iter != flist.end() )

           {

                     if( 3 == *iter )

                     {

                                iter = flist.erase_after( prev_iter );

                                continue;

                     }

                     ++prev_iter;

                     ++iter;

           }

 

           // 순회

           for( iter = flist.begin(); iter != flist.end(); ++iter )

           {

                     cout << *iter << endl;

           }

 

           return 0;

}

 

결과 >


 

위 예제를 보면 아시겠지만 forward_list std::list에 비해 성능 면의 이점을 가지고 있지만 사용 측면에서는 조금 불편한 점이 좀 있습니다그러나 C와 비슷한 성능을 내고 싶은 경우에는 좋은 선택 기가 될 수도 있습니다.

 


참고

http://msdn.microsoft.com/ko-kr/library/ee373568.aspx

저작자 표시
신고
by 흥배 2012.09.14 09:00

C++03까지의 STL에는 데이터셋에서 가장 작은 요소를 찾을 때는 min_element, 가장 큰 요소를 찾을 때는max_element를 사용하였습니다.

그런데 만약 최소와 최대를 동시에 찾을 때는 어쩔 수 없이 min_element max_element를 각각 호출해야 하는 불필요한 불편한 점이 있었습니다.

 

C++0x에서는 이런 불편함을 개선하기 위해 한번에 최소와 최고를 찾아주는 minmax_element 알고리즘이 새로 생겼습니다.

 

 

minmax_element

template<class ForwardIterator>

    pair< ForwardIterator, ForwardIterator >

        minmax_element( ForwardIterator _First, ForwardIterator _Last );

template<class ForwardIterator, class BinaryPredicate>

    pair< ForwardIterator, ForwardIterator >

        minmax_element( ForwardIterator _First, ForwardIterator _Last, BinaryPredicate _Comp );

 

minmax_element 알고리즘에는 조건자를 사용하는 버전과 조건자를 사용하지 않은 버전 두 가지가 있습니다데이터셋의 자료형이 유저 정의형(class struct를 사용한)이라면 조건자가 있는 버전을 사용합니다.

 

예제 코드 >

#include <iostream>

#include <algorithm>

using namespace std;

 

 

int main()

{

           int Numbers[10] = { 50, 25, 20, 7, 15, 7, 10, 2, 1, 3 };

          

           pair<int*, int*> MinMaxValue = minmax_element( &Numbers[0], &Numbers[10] );

 

           cout << "최소 값 : " << *MinMaxValue.first << endl;

           cout << "최대 값 : " << *MinMaxValue.second << endl;

          

           return 0;

}

 

결과 >


 

저작자 표시
신고
by 흥배 2012.09.06 09:30

is_sorted는 데이터셋이(컨테이너나 배열정렬되어 있다면 true를 반환하고그렇지 않다면 false를 반환 합니다.

is_sorted_until는 데이터셋에서 정렬되어 있지 않는 요소의 첫 번째 위치를 반환합니다.

 

is_sorted와 is_sorted_until의 원형은 아래와 같습니다.

is_sorted

template<class ForwardIterator>

    bool is_sorted( ForwardIterator _First, ForwardIterator _Last );


template<class ForwardIterator, class BinaryPredicate>

    bool is_sorted( ForwardIterator _First, ForwardIterator _Last, BinaryPredicate _Comp );

 

 

is_sorted_until

template<class ForwardIterator>

    ForwardIterator is_sorted_until( ForwardIterator _First, ForwardIterator _Last);

 

template<class ForwardIterator, class BinaryPredicate>

    ForwardIterator is_sorted_until( ForwardIterator _First, ForwardIterator _Last,

               BinaryPredicate _Comp );

 

위의 is_sorted와 is_sorted_until의 원형을 보시면 알겠지만 조건자(함수객체)를 사용하는 버전과 사용하지 않는 버전 두 가지가 있습니다.

조건자를 사용하지 않는 경우 기본으로 operator<가 적용됩니다.

 

프로그래머는 코드로 이해하죠? ^^ 그럼 바로 예제 코드 들어갑니다.

이번 예제는 간단하게 만들기 위해 정수 배열을 사용해 보았습니다아마 STL을 이제 막 공부하고 있는 분들은 알고리즘을 STL의 컨테이너에만 사용할 수 있는 것으로 알고 있는 분들도 있을텐데 그렇지 않습니다.아래 예제는 int 형 배열을 사용하였습니다.

 

예제 코드 >

#include <iostream>

#include <algorithm>

using namespace std;

 

 

int main()

{

           int Numbers1[5] = { 1, 2, 3, 4, 5 };

           int Numbers2[5] = { 5, 4, 3, 2, 1 };

           int Numbers3[5] = { 1, 2, 4, 3, 5 };

           bool IsResult = false;

 

          

           IsResult = is_sorted( &Numbers1[0], &Numbers1[5], [](int x, int y) { return x < y; } );

           cout << "Numbers1. 오름 차순 ? " << IsResult << endl;

 

           IsResult = is_sorted( &Numbers2[0], &Numbers2[5], [](int x, int y) { return x > y; } );

           cout << "Numbers2. 내림 차순 ? " << IsResult << endl;

 

           IsResult = is_sorted( &Numbers3[0], &Numbers3[5], [](int x, int y) { return x < y; } );

           cout << "Numbers3. 오름 차순 ? " << IsResult << endl;

 

           cout << endl;

           cout << "is_sorted에서 조건자(함수객체)를 생략한 경우 " << IsResult << endl;

           IsResult = is_sorted( &Numbers1[0], &Numbers1[5] );

           cout << "Numbers1 is_sorted의 결과는 ? " << IsResult << endl;

           IsResult = is_sorted( &Numbers2[0], &Numbers2[5] );

           cout << "Numbers2 is_sorted의 결과는 ? " << IsResult << endl;

 

           cout << endl;

           int Numbers4[8] = { 1, 2, 3, 5, 4, 5, 7, 8 };

           int* NumIter = is_sorted_until( &Numbers4[0], &Numbers4[5], [](int x, int y) { return x < y; } );

           cout << "Numbers4에서 정렬되지 않은 첫 번째 위치의 값 : " << *NumIter << endl;

 

           return 0;

}

 

결과 >


 

저작자 표시
신고
by 흥배 2012.09.05 19:28

VS2008까지는도구’ – ‘옵션메뉴를 통해서 VC++ 디렉토리를 설정하였습니다.

이렇게 설정한 정보는 모든 VC++ 프로젝트에 적용됩니다.

 

그러나 VS2010에서는 각 프로젝트 별로 VC++ 디렉토리를 설정합니다.


 

 

각 프로젝트 마다 독립적으로 설정을 할 수 있어서 편한 부분도 있지만 때로는 모든 프로젝트에 공통적으로 적용되어야 하는 경우는 매번 설정하는 것이 귀찮을 수 있습니다.

( 예로 DirectX boost 라이브러리 등 )

 

이런 경우속성 매니저를 통해서 VC++ 디렉토리를 설정하면 모든 프로젝트에 공통적으로 적용할 수 있습니다.

 

1. 일단 아무 프로젝트 하나를 열어 놓습니다.

2. 메뉴의보기’ -> ‘속성 관리자를 선택합니다.

 

 

3. 속성 관리자에서 ‘Microsoft.Cpp.Win32.user’를 더블 클릭해서 열어 놓습니다.


 

여기서 설정한 정보는 모든 프로젝트에 공통적으로 적용됩니다.

저작자 표시
신고
by 흥배 2010.10.28 09:00
| 1 2 3 4 |

티스토리 툴바