반응형


+ 적분팁 (Integration Tip)

-적분할 때 어떻게 접근하는게 빠를까?

아래 순서대로 접근해보면 도움이 많이 될 것이다. 1번이 안되면 2번으로 2번도 안되면 3번으로 등등 ...


1. 삼각 치환

아래 루트형태가 있을 때는 삼각함수로 치환한다.

로 치환한다. 

왜 그렇게 치환했는가?? 무조건 외우는건 금방 잊어 버린다. 왜 그런지 연상을 해야 잊어버려도 다시 유추하여 생각해 낼 수 있다.

생각해 보자... 보통 치환시키는 것은 치환한 것을 미분한 값이 나와야 치환한 의미가 있다.

치환한 x를 미분하면  .  쎄타 월드로 변경했을 때 미분한 값이 cos이 튀어 나온다.   그리고, x를 sin으로 치환하여 1-sin^2 형태가되어 루트를 씌우면 cos이 튀어 나오는  거랑 통하게 된 것이다.

이렇게 발상하면 지극히 당연히 sin으로 치환하는게 좋겠다는 생각이 든다.


로 치환한다.

루트 형태에서 1+tan^2은 sec^2이 되어 sec가 튀어나올 것이고, x를 미분하면 sec^2이 될 것이다. 비슷하다. 다른 항에 따라 잘될 수도 안될 수 도 있다.


로 치환한다.

루트형태에서 sec^2-1꼴이 나올 것이고, 여기서 루트를 씌우면 결국 tan가 튀어나올 것이고, x를 미분하면 sec * tan가 튀어나오게 된다. 이것도 주변 항에 따라 가능여부가 결정된다. 가장 좋은 것은 sec항이 있어준다면 럭키가 된다. 


2. 부분 적분

 이렇게 설명하기도 하고

 이렇게 설명하기도 한다. 똑같은 거다.

f'(x)를 dv라고 생각하고 f(x)를 v로 보면 된다. u는 g(x)이고, du는 g'(x)이다.

여기서 항상 고민인것은 어느 파트(dv)를 적분하고 어느 파트(u)를 미분할 것이지 선택하는 것이다. (어떤 것을 dv로 놓고 어떤 것을 u로 볼것인가?)

보통은 미분할 항(u)을 LIATE 순서로 선정한다..  그 의미는.

Logarithmic(ln), Inverse trigonometric (arctan, arcsin, ..) , Algebraic (5x^2, 3, ..) , Trigonometric(sin, cos..) , Exponential(10^x, e^x)

로그, 인버스, 대수, 삼각, 지수 

예를 들어 x e^x 를 적분한다고 하면, 대수와 지수함수가 나오므로 대수가 먼저 순서라그 대수인 x를 미분하고 e^x를 적분한다. 그렇게 하려면 x를 g(x) or u로 보고, e^x를 f'(x) or dv로 본다.


3. 유리 함수는 분모를 인수분해하여 부분분수형태로 접근한다.

분수꼴인 경우 분모를 인수분해하고 인수항들을 각각 분모로 하는 항들의 합인 형태로 변환한다. 분자는 a, b, c 등으로 놓고 통분했을때 원래의 형태가 맞게 나오게 방정식을 세워서 풀면된다.

예를 들면


4. 무리 함수는 루트부분을 치환한다. 통째로 할수도 있고 루트 x만 치환할 수도 있다. 

n제곱근과 m제곱근의 형태가 모두 나오면 n,m의 최소공배수 제곱근을 치환해 본다.

예를 들면 2제곱근 x + 3제곱근 x 이런 형태이면 6제곱근 x를 치환해 본다.


5. 지수함수를 치환한다. ( t = e^x )


6. 삼각함수들이 섞인 경우.

이것은 여러가지 접근해 시도해봐야 한다. 왕도는 없다.

sin, cos, tan, sec, csc, cot 들의 미분형태, 적분 형태를 어느 정도 알아야 한다. 외우기 힘들면 유도할 수 있어야 한다. 

sin, cos 배각 ( sin 2t = 2sin t cos t , cos 2t = cos^2 - sin^2 = 1-2 sin^2 = 2 cos^2 - 1)

cos^2 t = (1+cos2t) / 2

sin^2 t = (1-cos2t) / 2

1=sin^2+cos^2. 

분자 분모에 어떤 삼각함수를 곱할지..

무엇을 치환할 것인지. 치환할 부분을 미분하면 형태의 항이 나오게 되어 지워지는 부분이 있을지 등등...

짝수배 제곱의 형태이면 반각 공식등이 잘 먹히고   (sin^2 x = (1-cos 2t ) / 2 )

홀수배 제곱의 형태이면 하나를 분리하여 생각해 본다. ( sin^3 x  = sin x * sin^2 x )


7. inverse 삼각함수가 섞인 경우.

inverse함수를 원래 함수로 바꿔서 이것은 직각삼각형을 그려보면 다른 삼각함수들의 값을 쉽게 구할 수 있다.

arctan x = y 라면 tan y = x 가 되고, 직각 삼각형을 만들어 보고, 밑변을 1, 대변을 x, 끼인각을 y로 보면 된다. 빗변은 피타고라스로 구한다. 이제 cos y, sin y 를 쉽게 구할 수 있다.



'Math' 카테고리의 다른 글

root i, 허수 i의 루트. 이게 말이 돼?  (0) 2019.04.01
월리스(Wallis)의 곱. 이젠 이해할 수 있다.  (1) 2019.04.01
integral sec(x)  (0) 2019.03.28
integral csc(x)  (0) 2019.03.27
최소제곱법  (0) 2019.03.26
반응형


+ Python에서 Enum 사용하기


C나 C++에서 편하게 쓰던 enum이 python에서는 기본으로 없고 쓰기가 좀 불편합니다.

열거형(enum)은 상수와 같이 지정된 값을 이름을 부여하여 코드내에 가독성이 좋게 사용하기 위해 씁니다.

C로 예를 들면 상수타입을 그대로 쓸수도 있지만, 아래와 같이 불편합니다.

const int APPLE=1

const int BANANA=2

const int GRAPE=3

각각 값을 지정해 줘서 써도 되지만 번거롭습니다. 그래서 enum을 쓰죠.

enum Fruit {

APPLE=0,BANANA, GRAPE } ;

각 항마다 =1, =2 이렇게 값을 지정할수도 있고, 생략하면 순차적으로 이전 항보다 1씩 증가합니다. 

#include <stdio.h>


enum _fruit {

APPLE=0,

BANANA, GRAPE

};


int main()

{

enum _fruit a,b ;

a=APPLE ;

b=BANANA;

printf("a=%d\n", a) ;

printf("b=%d\n", b) ;

return 0 ;

}


C에서 보통은 좀 더 쓰기 편하기 typedef로 정의해서 사용하죠.

typedef enum _fruit {

APPLE=0,

BANANA, GRAPE

} FRUIT;


int main()

{

FRUIT a,b ;

a=APPLE ;

b=BANANA;

printf("a=%d\n", a) ;

printf("b=%d\n", b) ;

return 0 ;

}



파이썬에서는 enum을 아래와 같이 쓴다. 별도로 모듈을 임포트해줘야 한다. 

import enum


class Fruit(enum.Enum):

APPLE=0 

BANANA=1 

GRAPE=2


print(Fruit.APPLE)

print(Fruit.BANANA.value)

print(Fruit.GRAPE.value)


실행결과

Fruit.APPLE

1

2


값을 가져오려면 별도로 .value 프로퍼티를 써야 한다.

enum 변수값을 모두 각각 지정해 주어야 한다. 불편하다.


모듈 임포트 할 필요없이 별도로 함수를 만들어 enum을 쓰는 것이 편하다. 인덱스는 0부터 시작. 

def enum(*sequential, **named):

    enums = dict(zip(sequential, range(len(sequential))), **named)

    return type('Enum', (), enums)


Fruit = enum('APPLE','BANANA','GRAPE')


print(Fruit.APPLE)

print(Fruit.BANANA)

print(Fruit.GRAPE)


실행결과
0
1
2


반응형

+ sec x의 적분



분자 분모에 sec(x)+tan(x)를 곱한다.  (sec의 친구는 tan,  csc의 친구는 cot이다.)









+ sec x의 적분2










반응형

+ csc x의 적분



분자 분모에 csc(x)-cot(x)를 곱한다.










+ csc x의 적분2


-> 제곱의 형태로 만들어 다른 삼각함수로 변경한다. 


-> 부분분수로 쪼갠다.


--> 분모를 단항으로 만들기 위해 1+cos(x)를 분자,분모에 곱한다.






'Math' 카테고리의 다른 글

적분팁 (Integration Tip). 이것만 알아도 적분속도향상.  (3) 2019.03.29
integral sec(x)  (0) 2019.03.28
최소제곱법  (0) 2019.03.26
[선형대수] 프로젝션, 최소제곱법  (0) 2019.03.26
[미분] 미분  (0) 2017.05.08
반응형


+최소제곱법

샘플데이터들을 최대한 근사할 수 있는 하나의 직선이나 평면으로 모델링하여 다른 샘플들도 모델링한 시스템으로 예측할 수 있다.

실제 해(샘플데이터)와 모델이 예측한 결과와의 차이가 최소가 되게하는 방식.

샘플데이터 (x, Y)

y=ax+b 인 모델로 예측. 

에러값을  오차^2의 합으로 한다.  (Y-(ax+b))^2 으로 해야 맞는데, 제곱이므로 상관없다.

J(Cost) =  

위 Cost Function을  a, b로 각각 편미분하여 0이 되도록 한다. 최적화 문제.  (위 cost function이 convex 형태이기 때문에 가능하다. 아니면 local minima 문제가 있음.)



위 식을 정리하면

 : 1번식 

   : 2번식

2식을 n으로 나누면

   : 3번식

3번식에서 b를 구해 번식에 대입한다.

a로 묶어주면

양변을 n으로 나눠주면

a를 뺀 왼쪽부분을 잘 보면 (제곱의 평균 - 평균의 제곱)이다.  어디서 많이 본 형태이다. 이것은 x의 분산이다.

분산은 또 편차 제곱의 평균이다. 즉, 왼쪽 부분을  다르게 표현하자면 아래와 같다... (전개해서 계산하면 똑같다는 것을 알 수 있다.)

양변에 n을 곱하면 

오른쪽 부분을 정리하면 = Sigma (xy) - n * m_x * m_y
= Sigma (xy) + ( -n -n +n ) * m_x * m_y
 Sigma (xy) - m_y*n*m_x - m_x *n * m_y + m_x m_y n
 = Sigma (xy) - m_y Sigma(x) - m_x Sigma(y) + m_x m_y Sigma(1)
= Sigma (  xy  - x m_y - y m_x + m_x m_y )
= Sigma ( (x- m_x ) ( y - m_y ) ) 

따라서 a를 구할 수 있다.

a의 의미를 보자면, 

a= 편차곱의 합 / 편차제곱의 합

같은 값으로 분자 분모를 각각 n으로 나누게 되면 

a = 편차 곱의 평균 / x의 편차제곱의 평균이 되고, 이것은 

   =  x,y 공분산 / x의 분산.

결국 a 는 공분산을 x의 분산으로 나눈 값이된다.


a를 구한다음에는  b를 쉽게 구할 수 있다.  (3번식에 대입)



+예제)  임의의  점 7개를 생성. (black box 모델을 임의로 만들고 노이즈를 추가하였음.)

[Python Code]

import numpy as np
import matplotlib.pyplot as plt

# some data
x=np.random.rand(7)*10
print('x=',x)

# black box + noise
y=x*1.5 + np.random.rand(len(x))*3
print('y=', y)

# model : y = ax + b
mx = np.average(x)
my = np.average(y)

print('mx=', mx, ' my=', my)
a1=np.average((x-mx)*(y-my))
a2=np.average(np.power((x-mx), 2))
a=a1/a2
b=my - a * mx
print('a=',a, 'b=',b)

plt.figure()
plt.scatter(x,y, marker='o', c='blue')

# predict
newx=np.arange(0, 10, 0.2)
yy = a*newx + b
print('predict yy=', yy)
plt.scatter(newx,yy, marker='+', c='red')

plt.show()
[결과]
x= [ 5.91242894  8.31159962  5.84424276  1.6816099   3.96831144  5.44434753
  4.99976856]
y= [ 11.3111561   14.27345181   9.25338631   4.42757815   7.11410915
   8.43423682   7.51826014]
mx= 5.16604410833  my= 8.90459692524
a= 1.49495983563 b= 1.18156847417

임의의 파란점을 기반으로 최소제곱법으로 주어진 모델로 추정선을 만들어 그림.







'Math' 카테고리의 다른 글

integral sec(x)  (0) 2019.03.28
integral csc(x)  (0) 2019.03.27
[선형대수] 프로젝션, 최소제곱법  (0) 2019.03.26
[미분] 미분  (0) 2017.05.08
[적분] 곡선의 길이 계산2  (0) 2017.05.08
반응형


+ Projection / 프로젝션 / 투영

a벡터에 b벡터를 프로젝션시키면, b에서 a로 수선의 발을 내린다.  

project b onto a 라고 표현. (b를 a에 수직으로 내림. 수직으로 내리면 최단거리가 됨.)

수선의 발을 p라 하면. p점은 a 선상에 있고 p벡터를 a벡터의 상수배로 볼 수 있다.

   

b벡터 끝에서 p벡터에 가는 벡터와 a 벡터는 수직이다. 따라서 

수직인 벡터의 내적은 0이다. 열벡터에서 내적은 transpose의 곱으로 표현.

   ,     

여기서 매트릭스 연산식으로 바꾸고, 파라미터를 b로 보고 시스템을 꺼내보면. 프로젝션한 포인트 p는 

    ,    


이렇게 된다. 프로젝션 시스템 P는

이 변환 시스템이 어떤 점을 a 벡터로 프로젝션시키는 시스템이다.


프로젝션의 의미?

project b onto a (b를 a로 프로젝션 시킨다.)

     여기에서 는  a,b의 내적이다.  b를 a에 내린 사영의 크기 * a벡터의 크기이고,      는  a벡터 / a 벡터크기의 제곱.  즉, a 방향의 단위벡터 / a벡터의 크기가 되고,  이 둘을 곱하면  a벡터 크기 부분이 없어지므로  a 방향이고, 크기가 b를 a에 내린 사영의 크기인 벡터가 된다. 즉, 프로젝션이 된다.

b벡터에서 a벡터의 성분을 얼만큼 갖고있는지를 나타냄. 내적은 닮은 정도를 나타내기도 한다. 해당 성분이 얼만큼 있는지 나타내므로 닮은 정도이기도 하다. ( 내적이 a b cos (theta) 라는 의미를 생각해 보면 알 수 있다. 닮은 정도를 cos 유사도로 표현하는 것도 비슷하다. 두 벡터의 사이 각도가 0에 가까울 수록 비슷하고 cos값이 최대가 된다. 반대 방향으로 갈수록 작아진다.) 



+ 벡터의 투영과 최소 제곱

벡터와 평면이 수직인가를 알려면? 평면을  구성하는 기저벡터를 구하여 해당 벡터와 모두 수직인지 확인하면 된다.

임의 평면 x+2y+3z=0 의 기저 벡터를 구하려면?

위 방정식을 만족하는 독립인 벡터 두 개를 구하면 된다.

[1 1 1 ], [3 0 1]

위 두 개 벡터로 위 평면위의 모든 점을 스팬할 수 있다.

A는 위 기저벡터를 컬럼벡터로 하는 매트릭스로 어떤 시스템으로 볼 수 있다.

Ax는 위 평면위의 임의의 점이다. 기저벡터들의 선형결합으로 구성된 평면위의 점을 가리키는 벡터.

만약  평면 밖에 있는 b벡터를 A 평면에 내부의 벡터로 가장 가깝게 표현하려면??? 프로젝션!

즉, ||Ax-b||^2이 최소값이 되도록 한다. 최소제곱법.


Ax-b 벡터는 A 평면과 수직이다. 여기서 Ax는 b를 A 평면위에 프로젝션한 벡터이다. --> 최단 거리 지점.

b를 A에 프로젝션한 결과 : 




+ 실전

그렇다면 여러 점들을 가장 최적의 라인(또는 평면) 하나로 표현하려면?

측정값: (x1,y1), (x2,y2), (x3, y3), ...

피팅라인: y=ax+b   : 구하고자 하는 값 (a,b)

y1=ax1+b

y2=ax2+b

..

위 식을 모두 만족하는 a,b는 보통 존재하지 않는다. 다만 거리가 최소가 되도록 최적화된 라인을 찾을 수는 있다.

A x = b ( 왼쪽의 b는 위의 a,b 게수의 b와는 다른 것. y1,y2,y3를 말함)

x를 구하는 문제의 방정식을 만든다.

||Ax-b||^2 이 최소가 되게 하는 해를 구한다.

최소 거리를 만드는 문제는 프로젝션이다.

스페이스 밖의 점 b, 시스템은 A,   Ax는 b를 A에 프로젝션한 A 내부의 최적화된 점(p, 프로젝션)이 된다.

여기서 x를 구하면 최적화된 방정식의 계수인 a,b가 나온다.


) (x1,x2) -> y    이러한 함수가 y=ax1+bx2+c 이 모델로 만들어진다고 한다. 아래 점들에 최대한 근사한  평면으로 표현하라면 최적의 계수 a,b,c?

(0,0) -> 1

(2,2)->6

(1,4)->2

(4,6)->10



A=np.array([[0,0,1],[2,2,1],[1,4,1],[4,6,1]])

b=np.array([[1],[6],[2],[10]])

np.dot( np.dot( np.linalg.inv( np.dot(np.transpose(A), A)), np.transpose(A) ) , b)

Out[72]: 

array([[ 3. ],

       [-0.5],

       [ 1. ]])



+ python source  

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D


A=np.array([[0,0,1],[2,2,1],[1,4,1],[4,6,1]])
b=np.array([[1],[6],[2],[10]])

x = np.dot( np.dot( np.linalg.inv( np.dot(np.transpose(A), A)), np.transpose(A) ) , b)

print('A=',A)
print('b=',b)
print('x=',x)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

ax.scatter(A[:,0], A[:,1], b[:,0], marker='o', label='sample')

ax.set_xlabel('x1')
ax.set_ylabel('x2')
ax.set_zlabel('Y')
y = x[0]*A[:,0] + x[1]*A[:,1]+ x[2]
print('y=', y)
ax.scatter(A[:,0], A[:,1], y, marker='+', label='fitting')

# predict plane
x1=np.arange(0, 7, 0.2)
x2=np.arange(0, 7, 0.2)
x1,x2 = np.meshgrid(x1,x2)
Y = x[0]*x1 + x[1]*x2+ x[2]
ax.plot_surface(x1, x2, Y, alpha=0.2)


ax.legend()

plt.show()




파란점이 샘플 포인트이고 샘플 포인트에 최적화된 평면을 찾아 그 평면으로 다시 샘플포인트의 값을 추정하여 +로 표시하였음.   (거의 일치)

이렇게 프로젝션을 이용하여 최적화 할 수 있다. 


'Math' 카테고리의 다른 글

integral csc(x)  (0) 2019.03.27
최소제곱법  (0) 2019.03.26
[미분] 미분  (0) 2017.05.08
[적분] 곡선의 길이 계산2  (0) 2017.05.08
[적분] 곡선의 길이 계산  (0) 2016.09.06
반응형

파이썬에서 간단하게 랜덤 스트링 만들기



import string
import random

def random_string(size=6, chars=string.ascii_lowercase+string.digits):
return ''.join(random.choice(chars) for _ in range(size))



print( random_string(6) )
print( random_string(6) )
print( random_string(6) )

-위 함수에 파라미터로 랜덤스트링 길이를 넣어주면 된다.

-random.choice()는 내부에 아무 원소를 랜던하게 하나 뽑아준다.

-chars는 아래 정의된 값들을 사용.

-string.ascii_lowercase

Out[5]: 'abcdefghijklmnopqrstuvwxyz'

-string.digits

Out[6]: '0123456789'




반응형


+matplotlib subplot 화면분할 grid로 분할하기

HTML의 테이블의 TR, TD, colspan, rowspan 하듯이 그리드로 서브 플롯을 구성할 수 있다.


예제)

import matplotlib.pyplot as plt

import numpy as np


plt.figure(figsize=(15,8))

plt.subplots_adjust(hspace=0.5, wspace=0.4)

gridshape=(4,3)
loc=(0,0)

plt.subplot2grid(gridshape, loc, colspan=2)
plt.plot(np.arange(0,10,1), np.random.randint(0,10,10))

loc=(0,2)
plt.subplot2grid(gridshape, loc, rowspan=2)
plt.plot(np.arange(0,10,1), np.random.randint(0,10,10))

loc=(1,0)
plt.subplot2grid(gridshape, loc)
plt.plot(np.arange(0,10,1), np.random.randint(0,10,10))

loc=(1,1)
plt.subplot2grid(gridshape, loc )
plt.plot(np.arange(0,10,1), np.random.randint(0,10,10))

loc=(2,0)
plt.subplot2grid(gridshape, loc)
plt.plot(np.arange(0,10,1), np.random.randint(0,10,10))

loc=(2,1)
plt.subplot2grid(gridshape, loc)
plt.plot(np.arange(0,10,1), np.random.randint(0,10,10))

loc=(2,2)
plt.subplot2grid(gridshape, loc)
plt.plot(np.arange(0,10,1), np.random.randint(0,10,10))

loc=(3,0)
plt.subplot2grid(gridshape, loc, colspan=3)
plt.plot(np.arange(0,10,1), np.random.randint(0,10,10))


plt.show()


결과)





'Python' 카테고리의 다른 글

[Python] enum  (0) 2019.03.28
랜덤스트링 만들기  (0) 2019.03.22
File I/O, Directory list, read/write  (0) 2018.07.04
WebAPI thread work status  (0) 2018.07.03
Python BeautifulSoup 웹크롤링/HTML 파싱.  (0) 2018.04.25
반응형

+SVM (support vector machine)을 사용하여 간단하게 바이너리 분류하기


간단하게 말하면 가장 마진이 크도록 최적의 구분 라인 긋기. 약간의 판단 오류가 있더라면 데이터의 밀집 분포 정도에 따라 최적의 라인은 다를 수 있다. 판단오류가 하나도 없도록(과적합) 구분 라인을 만들면 오히려 임의의 값 예측시 정확도가 더 떨어질 수 있다. 


X 데이터 : 피쳐2개. 

Y데이터 : 라벨 (0, 1) binary 분류값.

SVM으로 최적 구분 라인 계산.

임의의 값에 대해 Y데이터 예측하기.


from sklearn.svm import SVC
import matplotlib.pyplot as plt
import numpy as np

# line split SVM

X = np.array([[1,2],
[5,8],
[1.5,1.8],
[8,8],
[1,0.6],
[9,11]])
y = [0,1,0,1,0,1]
clf = SVC(kernel='linear'1.0# C is error penalty. if C is bigger then more strictly but margin will be narrow...
clf.fit(X,y)
print(clf.predict([[0.58,0.76]]))
print(clf.predict([[10.58,10.76]]))

w = clf.coef_[0]
print(w)
a = -w[0] / w[1]

xx = np.linspace(0,12)
yy = a * xx - clf.intercept_[0] / w[1]

h0 = plt.plot(xx, yy, 'k-'label="non weighted div")

plt.scatter(X[:, 0], X[:, 1], = y)
plt.legend()
plt.show()

[해설]
x데이터의 벡터는 2차원이고 구분 레이블은 y로 0, 1로 두 그룹으로 나눈다.
SVC의 리턴값으노 clf로 피팅을 하게 되면
clf.predict()로 입력값 x에 대한 구분 레이블 y를 예측할 수 있다.

x데이터의 벡터요소(피쳐)를 x0, x1라 하면
새로운 좌표계의 1차원 좌표축을 z라하면
z = f (x0, x1) 
z>=0 이면 레이블1, z<0이면 레이블 0가 될 것이다. (z=0이면 1일까? 맞다.)

clf의 coef_로 w0, w1를 얻고, intercept로 b를 얻는다.
w0, w1는 입력값의 가중치. b 는 bias

z = w0*x0+w1*x1 + b 가 된다.
따라서 위 라인 (z=0으로 놓는다.)을 기준으로 분류한다.

위 라인을 x1(Y축)에 대해 정리하면
기울기는 -w0/w1
y절편은 -b/w1가 된다.
이 라인이 구분선이 된다.





반응형



+ 스마트포인터 (Smart Pointer) shared_ptr


동적으로 할당된 메모리를 관리하기 용이하다.
동작개념; 모든 것을 스택에 두어 로컬 변수로 관리하면 대부분의 메모리 문제가 해결된다는 것을 이용한다.
스택에 저장된 메모리는 스콥을 벗어나면 자동 해제되어 안전하다.

스콥을 벗어날때 참조된 메모리를 해제한다. unique_ptr 이 이러한 방식.
그러나 포인터를 복사하여 참조할 수 도 있어서 가장 마지막에 사용하는 곳에서 메모리 해제를 해야되는데, 트래킹을
하든지 해야된다. 참조가 0이되면 그 때 실제 해제되는 것이다. shared_ptr 이 이러한 방식.

C++표준 이전에는 auto_ptr을 사용했으나 폐기예정. (STL에서 사용시 문제 발생) 사용하면 안 됨.
C++11의 새로운 스마트 포인터는 unique_ptr, shared_ptr 이다.

unique_ptr ; 스코프 방식
shared_ptr ; 레퍼런스 카운팅 방식

-동적으로 메모리 할당한 객체라면 스택변수 shared_ptr에 항상 저장하라!
-동적메모리는 new든 malloc이든 할당과 동시에 shared_ptr에 저장하라!     

결국은 c++11에서는 항상 shared_ptr을 써라!!!


void leak(){
Simple *myptr = new Simple();
myptr->go();
} // 메모리 누수 발생. delete가 빠졌다.


#include <memory>
void noleak() {
shared_ptr<Simple> smartptr(new Simple() );
smartptr->go();
}     // 메모리 자동 해제.!!!!!!!!!!!


-스마트 포인터 사용 방법
shared_ptr<Simple> smartptr(new Simple() );
or
auto smartptr = make_shared<Simple>();


-주의!  shared_ptr을 한 객체에 하나만 생성해야 한다. 그렇지 않으면 중복해제가 됨. !! Warning!!

void a() {
Nothing *my = new Nothing();
shared_ptr<Nothing> sp1( my ) ;
shared_ptr<Nothing> sp2( my ) ;
}
// 에러위험. 위 함수가 실행되면, my객체의 constructor 1번 호출, destructor 2번 호출된다.

void a() {
Nothing *my = new Nothing();
shared_ptr<Nothing> sp1( my ) ;
shared_ptr<Nothing> sp2 = sp1 ;     // sp를 대입해서 참조해야 한다.
}
// ok. 위 함수가 실행되면, my객체의 constructor 1번 호출, destructor 1번 호출된다.





+ Recent posts