프로그래밍 일반 2014. 4. 2. 15:10

C++ 11 Range-based for loop

웹 컴파일러 링크 : http://melpon.org/wandbox/


Range for


range 안에서 STL의 begin(), end() 에서 하는 것처럼 루프를 실행한다.

모든 표준 컨테이너들은 range로 사용될 수 있고 std::string, initializer 리스트, 배열, 그리고 begin()과 end()를 정의할 수 있는 모든 것[각주:1]들이 사용 가능하다.


문법 

attr(optional) for ( range_declaration : range_expression ) loop_statement


위의 구문은 다음과 유사한 코드를 생성한다.

{

auto && __range = range_expression ; 

for (auto __begin = begin_expr,

__end = end_expr; 

__begin != __end; ++__begin) { 

range_declaration = *__begin; 

loop_statement 


샘플 코드

#include <iostream>

#include <vector>

 

int main() 

{

    std::vector<int> v = {0, 1, 2, 3, 4, 5};

 

    for (int &i : v) // access by reference (const allowed)

        std::cout << i << ' ';

 

    std::cout << '\n';

 

    for (auto i : v) // compiler uses type inference to determine the right type

        std::cout << i << ' ';

 

    std::cout << '\n';

 

    for (int i : v) // access by value as well

        std::cout << i << ' ';

 

    std::cout << '\n';

}


output

0 1 2 3 4 5

0 1 2 3 4 5

0 1 2 3 4 5


참고





  1. 예 istream [본문으로]
프로그래밍 일반 2014. 4. 2. 14:31

C++ 11 auto initializer

웹 컴파일러 링크 : http://melpon.org/wandbox/


auto initializer 로부터 타입을 유추


예를 들어 


auto x = 7;


위 코드에서 x는 initializer의 타입이 int 이기 대문에 int 타입이 된다.


일반적으로 우리는 


auto x = expression;

과 같은 구문을 보면 x는 expression 타입이 될 것이라고 생각한다.


 auto 를 사용하는 주된 이유는 어떠한 식의 타입이 알기 어렵거나 쓰기 매우 길 경우이다. 예를 들어

template<class T> void printall(const vector<T>& v) {

for (auto p = v.begin(); p != v.end(); ++p) {

cout << *p << "\n";

}

}

와 같은 코드를 이전 C++ 코드에서는 

template<class T> void printall(const vector<T>& v) {

for (typename vector<T>::const_iterator p = v.begin(); p != v.end(); ++p) {

cout << *p << "\n";

}

}

으로 작성해야만 했다. 또한 변수의 타입이 템플릿 인자에 의해 좌우 될 때, 이를 auto를 사용하지 않고 코드를 작성하려면 매우 까다롭다.

template<class T, class U> void multiply(const vector<T>& vt, const vector<U>& vu) {

// ...

auto temp = vt[i] * vu[i];

// ...

}

temp 의 타입은 T와 U를 곱한 것의 타입이 되어야만 하며, 이는 사람이 얽었을 때 무엇인지 생각하기에 까다롭지만 컴파일러는 어떠한 T와 U에 대한 처리인지 알기 대문에 위와 같이 표현할 수 있다.


 auto는 1984년에 이미 구현되었지만 당시의 C와 호환성 문제 때문에 사용할 수 없었다가 C++98 과 C99 에서 암시적 int[각주:1] 라는 것을 삭제함으로써 사용할 수 있게 되었다. 이제 두 언어 모두 모든 변수와 함수가 반드시 명확한 타입으로 정의 되어야만 한다. auto의 옛날 의미[각주:2]는 이제 사용할 수 없다.



참고






  1. 형식이 지정되지 않으면 int로 간주한다. [본문으로]
  2. 이 변수는 지역 변수이다 void f() { auto int i = 0; // C++0x에서는 오류 //... } [본문으로]
프로그래밍 일반 2014. 4. 2. 12:31

#ifdef __cplusplus 코드를 사용하는 이유

C++11 에는 매크로 __cplusplus 가 현재의 값인 199711L과 다른 (더 큰) 값으로 설정될 예정이라고 한다.


#ifdef __cplusplus

extern "C" {

#endif



#ifdef __cplusplus

}

#endif

가끔 위와 같은 코드를 보게 되는데 해당 코드는 __cplusplus 라는 것이 디파인되어 있으면 extern "C" { 를 삽입하라는 뜻이다. 이런 코드를 사용하는 이유는 C와 C++간의 링커 재사용을 위해서 이다. 처음 C++를 설계할 때 컴파일러만  새로 설계하고 링커는 기존 라이브러리를 재사용하려고 기존의 C링커를 그대로 사용하였다.  하지만 C++에서는 함수 오버로딩 등과 같은 기능을 지원하기 위해 각 함수명을 인자에 따라 컴파일러가 다르게 부여한다. (name mangling)

당연히 C에 있던 함수들도 다른 이름이 주어지게 되고 그럴 경우 라이브러리와 링크가 안된다. extern "C"라는 건 name mangling을 하지 않도록 하는 작업이다. 그렇게해야 C라이브러리를 링크할 수 있기 때문이다.

프로그래밍 일반 2014. 4. 1. 17:45

컴파일러 C++ 11 지원 여부 상태 & C++ FAQ




cplusplus_faq.pdf


프로그래밍 일반 2014. 4. 1. 12:38

클로저 Clojure

클로저 (Clojure)


 범용 함수형 언어, 이 언어는 불변값과 시간-진행 구문을 통한 프로그래밍을 강조하는데 이는 보다 탄탄한 프로그램, 특히 멀티스레드 개발을 용이하게 하기 위해서이다. 클로저는 자바 가상 머신과 공통 언어 런타임(CLR), 그리고 자바스크립트 엔진 상에서 실행된다. 다른 리스프 언어들과 같이 클로저는 코드를 데이터로 취급하며, 정교한 매크로 시스템을 갖고 있다.




기능


  • JVM 바이트코드 생성
  • 자바 프로그래밍 언어와의 밀접한 통합. 클로저 응용프로그램은 JVM 바이트코드로 컴파일되기 때문에 별다른 복잡한 과정없이도 JVM 환경이나 애플리케이션 서버 환경에 배포될 수 있다. 자바 API 를 단순하게 사용할 수 있는 매크로도 언어 차원에서 제공하고 있다. 클로저의 데이터 구조는 모두 자바의 표준 인터페이스를 구현하고 있어, 클로저에서 구현된 코드를 자바 코드 쪽에서 실행하기도 쉽다.
  • REPL 루프(read-eval-print loop) 환경에서의 빠른 개발
  • 일급 객체로서의 함수
  • 부수효과 기반의 반복문보다는 재귀와 고계함수 (higher-order function)[각주:1]의 활용을 강조
  • 지연 평가[각주:2]되는 시퀀스 (sequence)
  • 풍부한 불변값, 영구 보존적 데이터 구조(persistent data structure)를 지원(해시맵, 집합, 리스트 등)
  • 소프트웨어 트랜잭셔널 메모리[각주:3], agent system, dynamic var system 을 통한 동시성 프로그래밍
  • 임의적인 개수의 인자들의 타입과 값에 대한 다중 동적 디스패치 (참고로, 일반적인 객체 지향 시스템에서 구현된 다형성 개념은 첫 번째 인자의 타입만으로 동적 디스패치 하는 것임)



Hello World


콘솔

(println "Hello world!")


스윙을 호출하여 GUI에 출력

(javax.swing.JOptionPane/showMessageDialog nil "Hello World!")







  1. 함수를 다루는 함수, 함수도 'VALUE' 취급 어떤 함수도 다른 함수의 인수로 전달할 수 있고 리턴값으로 함수를 반환할 수 있다 [본문으로]
  2. Lazy evaluation 계산의 결과값이 필요할 때까지 계산을 늦추는 기법 [본문으로]
  3. 현대의 다중 스레드 응용 프로그램에서 사용하는 락(lock)과 달리, 트랜잭셔널 메모리는 보다 낙관적인 전략을 사용한다. 트랜잭셔널 메모리를 사용하는 스레드는, 다른 스레드에서 실행되는 코드가 해당 메모리를 간섭하지 않을 것으로 가정하고 읽기 및 쓰기를 수행하며, 읽기와 쓰기를 수행한 메모리의 주소를 기록한다. 트랜잭션 영역의 수행이 완료되면, 해당 메모리 주소가 다른 스레드에 의해 변경되었는지 검사한다. 만약 변경이 없었다면, 트랜잭션은 올바르게 수행되었으므로 커밋(commit)이 이루어지고, 그렇지 않으면 트랜잭션은 실패한다. 트랜잭션이 실패했을 경우 트랜잭션을 재시도할지, 아니면 취소할지는 프로그래머가 선택할 수 있다. 또한 트랜잭션은 언제든 중간에 취소하여 트랜잭션 수행 이전 상태로 되돌아갈 수 있다. 기존의 락 기법에 비해 트랜잭셔널 메모리의 장점은, 더 많은 스레드가 동시에 수행될 수 있다는 것이다. 락이 해제되길 기다리며 대기하는 스레드가 없고, 충돌이 일어나지 않으면 모든 스레드가 자신의 코드 영역을 안전하게 수행할 수 있다. 그러나, 트랜잭셔널 메모리는 읽기 및 쓰기를 수행한 메모리 주소를 기록하는 오버헤드로 인해 약간의 성능 저하가 존재한다. 소프트웨어적으로 구현한 트랜잭셔널 메모리의 경우 이 오버헤드가 큰 편이다. [본문으로]
프로그래밍 일반 2014. 4. 1. 11:51

자바스크립트 JavaScript

스크립트언어 Scripting language


스크립트 언어는 프로그램과 독립하여 사용되고 일반적으로 응용프로그램의 언어와 다른언어로 사용되어 최종 사용자가 응용프로그램의 동작을 사용자의 요구에 수행할 수 있도록 해준다. 스크립트는 연극 용어에서 유래되었으며 초창기 스크립트 언어는 배치언어 (batch languages) 또는 작업 제어 언어(job control language)라고도 불리었다.




자바스크립트 JavaScript


객체 기반의 스크립트 프로그래밍 언어

웹 사이트에서 많이 사용하며, 다른 응용프로그램의 내장 객체에도 접근할 수 있는 기능을 가지고 있다. 자바스크립트가 썬 마이크로시스템즈의 자바와 구문이 유사한 점도 있지만, 이는 사실 두 언어 모두 C언어의 기본 구문을 바탕으로했기 때문이고, 자바와 자바스크립트는 직접적인 관련성이 없다. 이름과 구문 외에는 자바보다 셀프와 유사성이 많다.


모카(Mocha) -> 라이브스크립트(LiveScript) -> 자바스크립트(JavaScirpt)


2013년 1월 기준으로 최신 버전은 자바스크립트 1.8.5, 표준 ECMA-262 3판 (edition)에 대응하는 버전은 1.5이다. ECMA스크립트는 쉽게 말해 자바스크립트의 표준화된 버전이다. 자바스크립트는 브라우저마다 지원되는 버전이 다르다.




서버사이드 자바스크립트 CommonJS, AMD등의 모듈화


2005년 Ajax가 활성화되면서 자바스크립트의 연산이 증가했고 자연스럽게 더욱 빠른 자바스크립트 엔진의 필요성이 대두되었다. 이런 맥락에서 2008년 구글이 공개한 V8 엔진은 많은 주목을 받았는데 기존 자바스크립트 엔진보다 월등히 빨랐을 뿐만 아니라, 브라우저 밖에서도 충분히 쓸만한 성능을 자랑했다. 

 V8 엔진의 등장은 서버사이드 자바스크립트 진영에 활기를 불어넣게 되었는데 자바스크립트는 모듈화를 언어 자체에서 지원하지 않았다. 때문에 모듈화에 필요한 여러 요소들이 존재하지 않기에 별도의 표준이 필요했고 그 결과 탄생된 표준 이 CommonJS, AMD이다. 이들의 목표는 자바스크립트의 표준 라이브러리를 만드는 것이었다.



http://www.commonjs.org/

https://github.com/amdjs/amdjs-api/wiki/AMD




주요 쟁점

  • 서로 호환되는 표준 라이브러리가 없다.
  • 데이터베이스에 연결할 수 있는 표준 인터페이스가 없다.
  • 다른 모듈을 삽입하는 표준적인 방법이 없다.
  • 코드를 패키징해서 배포하고 설치하는 방법이 필요하다.
  • 의존성 문제까지 해결하는 공통 패키지 모듈 저장소가 필요하다.
앞에서 언급한 문제점들은 결국 모듈화로 귀결된다. 그리고 CommonJS의 주요 명세는 바로 이 모듈을 어떻게 정의하고, 사용할 것인가에 대한 것이다.


모듈화는 세 부분으로 이루어진다.

  • 스코프 (Scope) : 모든 모듈은 자신만의 독립적인 실행 영역이 있어야 한다.
  • 정의 (Definition) : 모듈 정의는 exports 객체를 이용한다.
  • 사용 (Usage) : 모듈 사용은 require 함수를 이용한다.

fileA.js

var a = 3;

b=4;

exports.sum = function(c, d) {

return a + b + c + d;

}



fileB.js

var a = 5;

b = 6;

var moduleA = require("fileA");

moduleA.sum(a,b); // 3+4+5+6 = 18


예에서 CommonJS 모듈의 명세는 모든 파일이 로컬 디스크에 있어 필요할 때 바로 불러올 수 있는 상황을 전제로 한다. 하지만 이런 방식은 브라우저에서는 결정적인 단점이 있다. 필요한 모듈을 모두 받을 때까지 아무것도 할 수 없기 때문이다. 해결법은 동적으로 <script> 태그를 삽입하는 방법..



비동기 모듈 로드 문제


JavaScript가 브라우저에서 동작할 때는 서버 사이드 JavaScript와 달리 파일 단위의 스코프가 없다. 또한 표준 <script> 태그를 이용해 앞에서 예로 든 fileA와 fileB를 차례대로 로드하면, fileB의 변수가 fileA의 변수를 모두 덮어쓰게 되는 전역변수 문제도 발생한다.


이런 문제를 해결하려고 CommonJS는 서버 모듈을 비동기적으로 클라이언트에 전송할 수 있는 모듈 전송 포맷(module transport format)을 추가로 정의했다. 이 명세에 따라 서버사이드에서 사용하는 모듈을 다음 예의 브라우저에서 사용하는 모듈과 같이 전송 포맷으로 감싸면 서버 모듈을 비동기적으로 로드할 수 있게 된다.


서버사이드에서 사용하는 모듈

// complex-numbers/plus-two.js

  

var sum = require("./math").sum;

exports.plusTwo = function(a){

return sum(a, 2);

};



브라우저에서 사용하는 모듈

// complex-numbers/plus-two.js

  

require.define({"complex-numbers/plus-two": function(require, exports){

  

//콜백 함수 안에 모듈을 정의한다.

var sum = require("./complex-number").sum;

exports.plusTwo = function(a){

return sum(a, 2);

};

},["complex-numbers/math"]);

//먼저 로드되어야 할 모듈을 기술한다.

브라우저에서 사용하는 모듈 부분에서 특히 주목해야 할 것은 require.define() 함수를 통해(함수클로저) 전역 변수를 통제하고 있다는 사실이다.


본래 CommonJS가 JavaScript를 브라우저 밖으로 꺼내기 위한 노력의 일환으로 탄생했기 때문에 브라우저 내에서의 실행에 중점을 두었던 AMD와는 합의를 이끌어 내지 못하고 결국 둘이 분리되었다


두 진영에서 정의하는 모듈 명세의 차이는 모듈 로드에 있다.


필요한 파일이 모두 로컬 디스크에 있어 바로 불러 쓸 수 있는 상황, 즉 서버사이드에서는 CommonJS 명세가 AMD 방식보다 간결하다. 반면 필요한 파일을 네트워크를 통해 내려받아야 하는 브라우저와 같은 환경에서는 AMD가 CommonJS보다 더 유연한 방법을 제공한다.



ConTexts VS Scope


모든 함수의 실행은 스코프, 그리고 스코프와 연결된 컨텍스트를 갖는다. 근본적으로 스코프는 함수 기반이고, 컨텍스트는 객체 기반이다. 다시 설명하면 스코프는 함수가 실행될 때 그리고 각각의 실행에 대해서 그 함수의 접근이 달라지는 것을 말한다. 컨텍스트는 항상 this 키워드의 값이며, 현재 실행되는 코드를 소유하는 객체의 레퍼런스를 가리킨다.



this 컨텍스트란?

컨텍스트는 거의 대부분 함수가 어떻게 실행되느냐에 따라 결정된다. 함수가 객체의 메소드로서 불리게 되면, this는 메소드를 부른 객체로 설정된다.


실행 컨텍스트와 스코프 체인


자바스크립트는 싱글 스레드로 작동하는 언어라서, 브라우져에서 한번에 한가지만 할 수 있다. 자바스크립트 인터프리터가 초기에 코드를 실행할 때는, 기본적으로 글로벌 컨텍스트에서 실행하며 들어간다. 그리고 각 함수가 실행될 때마다 새로운 실행 컨텍스트가 생기게 된다.


"실행 컨텍스트"라는 단어는 실제로 그 의도나 목적들이 스코프에 관련된 것이지 앞에서 이야기한 컨텍스트가 아니여서 혼란이 생긴다. 이런 애매한 명명 규칙은 ECMAScript 스펙에 정의된 단어라서 더 구리다.


새로 실행 컨텍스트가 생길 때마다 스코프체인이라 불리는 곳의 맨 위에 붙게 된다. 브라우져는 항상 스코프체인의 최상위를 실행한다. 한번 완료되면 스택의 맨 위에서 사라지게 되고, 컨트롤은 그 아래의 실행 컨텍스트로 넘어간다. 예제를 보자.


function first(){

    second();

    function second(){

        third();

        function third(){

            fourth();

            function fourth(){

                // do something

            }

        }

    }   

}

first();

위의 코드가 실행되면 중첩된 함수들을 따라서 fourth 함수까지 따라 내려온다. 이 때 스코프체인은 위에서부터 아래로, fourth, third, second, first, global이 될 것이다. fourth 함수는 전역변수나 first, second, third 및 그 자신의 내부에 있는 어떤 변수들에도 접근할 수 있다. fourth 함수의 실행이 끝나게 되면 스코프체인에서 빠지고 실행은 third에서 계속된다. 이 과정은 모든 코드의 실행이 완료될 때까지 계속된다.


다른 실행 컨텍스트들 사이에서 변수명이 충돌나면 스코프체인을 로컬에서 글로벌로 타고 올라가면서 찾는다. 이는 같은 이름의 변수가 있을 때 스코프 체인에서 로컬 변수가 제일 우선순위가 높다는 뜻이다.


실행 컨텍스트는 생성과 실행 부분으로 나눌 수 있다. 생성 부분에서 인터프리터는 모든 변수들, 함수 선언, 실행 컨텍스트 내부에 정의된 인자들로 이루어진 변수 객체(혹은 활성 객체-activation object-라 불리는)를 만든다. 다음으로는 스코프 체인이 초기화되고, 값이 결정되는건 마지막이다. 그리고 실행 부분에서는 코드를 한줄씩 읽어서 실행한다.


간단히 말해서, 함수의 실행 컨텍스트 내에서 변수에 접근할 때마다 항상 그 실행 컨텍스트의 변수 객체에서 부터 탐색이 시작된다. 변수 객체에서 변수를 찾을 수 없으면 스코프체인에서 탐색이 계속된다. 스코프체인을 따라 올라가면서 변수명이 있는지 모든 실행 컨텍스트의 객체 변수를 확인한다.




자바스크립트 스코프 (Scope)


변수가 스크립트 안의 어느 장소에서 참조할 수 있는가에 대한 개념


자바스크립트 스코프에는 스크립트 전체에서 참조할 수 있는 글로벌 스코프와 정의된 함수 안에서만 참조할 수 있는 로컬 스코프로 분류할 수 있다.

자바의 스코프는 블록 스코프 즉 {} 안에서의 스코프 유지가 가능했지만, 자바스크립트에서는 이를 지원하지 않으니


if ( a > b ) {

var c;

}


같은 구문을 사용할 때 c는 if문이 끝나도 유지된다.

또, 로컬 스코프 사용에 유의해야되는데 


var scope = "Global";  

  

function getValue() {  

   document.writeln(scope);  

   var scope = 'Local Variable';  

   return scope;  

}  

  

document.writeln(getValue()); //Local variable  

document.writeln(scope); // Global  

위의 구문에서  함수 가장 첫줄에 보여지는 scope 값이  로컬 변수가 세팅되기 전이라 글로벌 스코프 값인 Global이 출력될 것이라 생각하기 쉽지만, 실제로는 undefined가 출력된다.

이는 로컬 변수가 함수가 실행되는 시점에서 이미 유효하기 때문이다.

다만 아직 초기화가 이루어지지 않았기 때문에 undefined가 출력된다.




자바스크립트 클로져 (Closure)


클로져는 그 함수의 지역 변수가 아닌 것들을 위한 참조 환경을 함께 가지고 있는 함수(실행코드)이다. 

자바스크립트의 모든 함수는 그 함수의 지역 변수가 아닌 것들을 위한 참조 환경을 함께 가진다.


클로져의 가장 핵심적인 개념은 어휘적인 유효 범위이다. 함수가 실행될 때는 함수가 실행되는 위치가 아닌, 함수가 정의 될 당시의 유효범위에서 실행된다. 브라우져의 가비지 컬렉터는 보통 함수의 로컬 변수의 경우 함수의 실행이 끝나는 시점에 메모리를 해제해버리지만, 클러져의 속성을 유지하기 위해 로컬 변수를 사용하는 함수가 밖으로 내보내질 경우 메모리를 해제하지 않고 해당 값을 유지한다.


클로져는 지역변수의 한계를 극복하여 함수 호출의 경계를 넘어서도록 지역변수를 확장하여 사용하는 기법을 가능하게 한다.



function foo(){

    var local = 'private variable';

    return function bar(){

        return local;

    }

}


var getLocalVariable = foo();

getLocalVariable() // private variable

 중첩된 함수가 있을 때 그 변수가 정의된 함수의 밖에서 접근하는 형태이며, 리턴된 함수로 외부에서 실행될 수도 있다. 함수 외부에서 로컬 변수들, 인자들, 내부에 선언된 함수에 계속 접근할 수 있다. 캡슐화는 바깥 스코프에서 실행 컨텍스트를 숨기고 보호하며, 공개적인(public) 인터페이스를 드러내서 관리할 수 있다. 


클로저의 가장 유명한 타입 중 하나인 모듈 패턴


var Module = (function(){

    var privateProperty = 'foo';


    function privateMethod(args){

        //do something

    }


    return {


        publicProperty: "",


        publicMethod: function(args){

            //do something

        },


        privilegedMethod: function(args){

            privateMethod(args);

        }

    }

})();

모듈은 싱글톤처럼 작동하며, 함수의 끝에 있는 열고 닫는 괄호 때문에 컴파일러가 읽자마자 실행된다. 이 클로져의 실행 컨텍스트 외부에서는 접근할 수 있는 멤버들은, 반환된 객체에 있는 메소드들과 속성들이다. (예를 들어, Module.publicMethod) 그러나, 모든 private 속성들과 메소드들은 숨겨진 실행 컨텍스트로 애플리케이션이 끝날 때까지 살아남아 있는데, public Method들을 통해 변수들을 접근 할 수 있다는 뜻이다.

프로그래밍 일반 2014. 3. 31. 17:55

자바와 C++의 차이

설계 목표


 C++는 이름에서 나타나듯이 C를 확장하여 만들었다.

절차적 프로그래밍 언어에 효율적인 실행을 목표로 설계, 정적 자료형 검사, 객체 지향 프로그래밍, 예외 처리, RAII, 제네릭 프로그래밍을 지원한다. 범용 컨테이너와 C++ 표준 라이브러리도 추가되었다.


 자바는 처음에는 가전제품에 탑재되어 네트워크 컴퓨팅을 지원하기 위해 만들었다. 가상 머신에서 실행되기 때문에 안전성을 가지며 또한 이식성이 높다. 하위 플랫폼을 완벽하게 추상화시켜 주는 광대한 분량의 라이브러리를 가지고 있다. C와 비슷한 문법을 사용할뿐 직접적인 호환성은 없다. 사용하기 편하고 많은 사람이 이해하기 쉬운 언어를 목표로 설계되었다.


두 언어는 개발의 목적이 다르기 때문에 결과적으로 서로 다른 원리, 방침, 설계에서 트레이드오프에 차이가 생겼다.


 C++

자바 

 C 소스 코드와 하위 호환성

다른 언어와 소스 코드 호환성은 없다. 

 직접적인 시스템 라이브러리 호출 가능

Java Native Interface를 이용 

 저수준 시스템 접근 가능

안전하게 보호되는 가상 머신위에서 실행됨 

 선택적 자동 경계 검사

항상 자동 경계 검사함 

 부호없는 연산 지원

부호없는 연산 지원 안함 

 값에 의한 매개변수 전달 또는 참조에 의한 매개변수 전달

항상 값에 의한 매개변수 전달. 매개변수로 객체에 대한 참조값을 사용할 수는 있다. 참조 대상의 내용을 변경할 수는 있지만, 참조값 자체는 변경할 수 없다. 메서드 호출 후에도 참조하는 객체는 다른 객체로 바뀌지 않을 것이다.

 명시적 메모리 관리, 가비지 콜렉션은 추가적으로 라이브러리를 이용해야 한다.

항상 자동 가비지 콜렉션 

 명시적인 자료형 재정의 허용

자료형 안전성에 엄격함 

 C++ 표준 라이브러리는 적절한 범위까지 지원함

방대한 분량의 라이브러리 

 연산자 오버로딩

 연산자 오버로딩 할 수 없음


C++는 강력하지만 복잡하고 어려운 언어로, 성능 위주의 응용 프로그램이나 라이브러리에 적당하다. 자바는 대개 배우기 쉽지만 플랫폼 자체가 가지는 전체 기능 이용이나 완벽한 성능 활용을 기대하기는 어렵다.


프로그래밍 일반 2014. 3. 31. 11:54

RAII C++

Resource Acquisition Is Initialization


RAII는 C++에서 자주 쓰이는 IDIOM으로 자원의 안전한 사용을 위해 객체가 쓰이는 범위를 벗어나면 자원을 해제해주는 기법이다.

C++에서 힙에 할당된 자원은 명시적으로 해제하지 않으면 해제되지 않지만, 스택에 할당된 자원은 자신의 범위가 끝나면 메모리가 해제되며 소멸자가 불린다는 원리를 이용한 것이다.

원래는 EXCEPTION 등으로 제어흐림이 예상치 못하게 변경될 때를 대비하기 위해서 쓰이던 기법이다.






첫번째 코드는 예외 발생시 리소스를 해제하지 못한다.

두번째 코드는 리소스를 해제하고 있지만 가시성이 나쁘고 , 유지하기도 어려워진다.

세번째 코드는 RAII를 위해 C++ 11의 스마트 포인터인 unique_ptr을 이용하는 방법이다.


여기서 말하는 자원은 단순히 힙 메모리만이 아니라, 파일이나 DB와 같은 것들도 전부 RAII를 이용해 안전하게 사용할 수 있다.

특정 범위를 벗어나면 반드시 실행되야하는 코드들도 RAII를 이용해 처리할 수 있다. 즉, 다른 언어에서 FINALLY에 해당하는 구문을 RAII를 이용해서 처리할 수 있다. 실제로 C++의 아버지이자 RAII라는 용어를 처음 만든 Bjarne Stroustrub는 C++에 finally를 집어넣지 않은 이유를 

 "RAII가 있는데 굳이 있을 필요가 없다."

라고 말하고 있다.

프로그래밍 일반 2014. 3. 31. 10:48

자바

바이트 코드


VM에서 돌아가는 실행 프로그램을 위한 이진 표현법

  • 기계어 보다 추상적 (소프트웨어에 의해 처리)
  • 특정 하드웨어에 대한 의존성을 줄인다.
  • 특정 하드웨어의 기계 코드를 만드는 컴파일러의 입력으로 사용되거나 가상 컴퓨터에서 바로 실행한다. (인터프리터보다는 빠른 이유)
  • 소스 코드와 비교하면 덜 추상적이며, 더 간결하고, 더 컴퓨터 중심적이다.  ( 변수의 접근 범위 등과 같은 의미 분석 단계의 결과를 부호화하기 때문에 일반적으로 소스 코드를 분석/실행하는 것보다 더 좋은 성능을 보여준다.)


자바

객체 지향적 프로그래밍 언어 Java Standard Edition 8 (1.8.0) / 2014년 3월 19일

컴파일된 코드가 플랫폼 독립적

  • 자바 컴파일러는 자바 언어로 작성된 프로그램을 바이트 코드라는 특수한 바이너리 형태로 변환
  • 바이트 코드를 실행하기 위해서는 JVM 필요
  • CPU나 운영체제의 종류에 관계없이 JVM을 설치할 수 있는 시스템에서는 어디서나 동일한 형태로 실행이 가능하다.
  • JVM은 CPU와 직접적으로 관계가 있으므로 CPU의 기계어 코드로 이루어진다.
  • 단점은 C/C++ 코드로 작성되어 생성된 코드 보다 실행 속도가 느리다.





JVM 구조


소스 코드는 바이트 코드로 컴파일되어 실행, 코드 검증

JVM에 의해 해석되어 실행(interpreted) 또는 JIT-compiled로 직접 기계어 코드로 변환 실행, JRE (Java Runtime Environment)에 API와 JVM이 함께 만들어짐




Hello world


public class HelloWorldApp {

     public static void main(String[] args) {

         System.out.printIn("Hello World!");

     }

}

소스 파일명은 반드시 파일 내의 public class 이름과 동일해야 하며, 파일 확장자는 .java 이어야 한다.

예를 들면, 만약 public class 이름이 HelloWorldApp 이라면, 파일명은 반드시 HelloWorldApp.java가 되어야 한다.

이 자바 파일이 동작하기 위해서는 자바 컴파일러를 통해서 바이트 코드로 컴파일되어 같은 이름의 .class 파일, 즉, HelloWorldApp.class가 생성되어야 한다.

컴파일된 class 파일은 자바 가상 머신을 통해 실행이 가능하다.


리눅스/유닉스 터미널 (혹은 윈도 cmd) 에서 자바 파일을 컴파일한 후 실행하는 방법 예제)


컴파일: 자바 컴파일러 사용 (예, javac)

javac HelloWorldApp.java

컴파일 후에는 같은 이름의 class 파일인 HelloWorldApp.class가 생성된다.


실행: 자바 가상 머신 사용 (예, java)

java HelloWorldApp

실행 시에는 확장자인 .class를 붙이지 않는다.


결과

Hello World!

프로그래밍 일반 2014. 1. 13. 11:54

map과 함수 포인터를 이용해서 switch - case 구문 단순화 시키기..


 장점.. 보기 편하고 , 스택 오버플로우가 방지되며, 빠르다.

 switch - case 는 관리를하지 않으면 최적화(goto)가 되지 않는다..


단점 - 사용하기에 따라서는 thread safe하지 않다.

    thread safe 하도록 객체를 생성하자.


샘플 코드..


// 이벤트...

 enum ECondition {

eNull,

ePlay,

eWin,

eConnection,

eMax;

};


struct SCollect;

struct SData;


// 이벤트 로직 구현

BOOL ProcessBase(const SCollect& collect, const SData& data) {

// 기본로직

return TRUE;

}


BOOL ProcessPlay(const SCollect& collect, const SData& data) {

// 승리 관련... 블라블라..

return TRUE;

}



class CFuncMap 

{

private :

CFuncMap() {


// 특별 루틴 선등록

Regist(ePlay, ProcessPlay);


// 기본 처리 루틴 셋팅

for (int iCondition = ePlay; iCondition < eMax; ++iCondition ) {


Regist(static_cast<ECondition>(iCondition));

}

}



public :

typedef BOOL (*PFUNC)(const SCollect&, const SData&);

~CFuncMap() {}


static CFuncMap& GetInstance() {

static CFuncMap instance;

return instance;

}


PFUNC GetFunc(ECondition condition) {


FUNCMAP::const_iterator iter_func = m_funcTable.find(condition);

return (m_funcTable.end() != iter_func) ? iter_func->second : NULL;

}


private :

void Regist(ECondition condition, PFUNC pFunc = ProcessBase) {

m_funcTable.insert(std::make_pair(condition, pFunc));

}


private :

typedef std::map<ECondition, PFUNC> FUNCMAP;


FUNCMAP m_funcTable;

};




/// 코드 어딘가

void Process() {


// 이벤트를 처리하는 부분..

ECondition eEvent = eNull;

CFuncMap::PFUNC pFunc = CFuncMap::GetInstance().GetFunc(eEvent);


if ( NULL != pFunc ) {


(*pFunc)(collect, data);

}

}