int a[] = {2,4,6,8}; // 전역변수, 데이터영역, a의 주소 0x10e26???
double d[] = {1.0,3.0,5.0};
int main(){
//int a[4] = {2,4,6,8}; // 로컬변수, 스택영영, a의 주소 0x7ffe????
int *a = malloc(sizeof(int)*10); //new 와 비슷, int의 10개 크기만큼 heap에 생성
a[0] = 2; // *(a+0) == 1
a[1] = 4;
a[2] = 6;
// c언어는 gc가 없으니까 수동으로 free() 해줘야함.
printf("address: %p", a);
printf("%d\n",*a); // output: 2 == a[0]
printf("value *a: %d\n", *(0+a)); // 0+a , a+0 가능 , 교환법칙 성립, 이건 c언어에서만 성립됨.
printf("value *a: %d\n", 0[a]); // a[b] = *(a+b) 정수연산이 되네..?, 덧셈의 교환법칙이 성립하고..
printF("value *(a+2): %d\n", 2[a]) //output 6 == *(a+2)
// 이렇게 배열을 만든 장점은
-- 배열의 임의의 원소에 접근할 때 복잡도가 1임.
-- 단순히 주소의 덧셈 연산만으로 접근이 가능.
-- 이게 c언어의 배열이라는 것에 정체
-- 공간복잡도도 줄일 수 있음. 메모리에 주르륵 쌓으면 됨.
int *b = a;
printf("a == b ? %d\n", a == b); // output: true
b=b+1; // b의 주소값이 한 칸 더가게됨.
printf("address b: %p\n", b+1);
printf("value *b : %d\n",*(b+1)); //output: 4
double *p = d; // double형 포인터
printf("addres %p\n", p);
printf("address p +1 %p \n", p+1);
printf("address p +1 %f \n", *(p+1));
free(a); // 자바의 IO close를 비슷. 메모리 해제의 책임을 개발자가 쥔다.
// 안할경우 Memory leak 발생
// 장기적으로 프로그램이 죽는 원인이 됨.
return 0;
}
Almighty
하다라는 게 가정이었다고 한다.
void each(int *a, int size, void (*apply)(int){ // void (*apply)(int) :: 매게변수가 int
for(int i=0; i<size;i++){
apply(a[i]);
}
}
void foo(int x){
printf("x: %d \n", x);
}
int main(){
int a[] = {1,2,3};
foo(a[0]);
printf("P: %p\n", foo); // 코드영역에 존재함.
each(a, 3, foo); //
return 0;
}
public interface Cloneable {}
Bill Venners: In your book you recommend using a copy constructor instead of implementing
Cloneable
and writingclone
. Could you elaborate on that?
Josh Bloch: If you've read the item about cloning in my book, especially if you read between the lines, you will know that I think clone is deeply broken. There are a few design flaws, the biggest of which is that theCloneable
interface does not have aclone
method. And that means it simply doesn't work
...
@Override
public Circle clone(){ //m 깊은 복사, 공변 반환타입 ( Object -> Circle )
Object obj = null;
try {
obj = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
Circle c = (Circle)obj;
c.p = new Point(this.p.x, this.p.y);
return c; // 공변 반환타입
}
obj = super.clone()
이 부분이 단순히 Object obj = Object target
이런 느낌인줄 알아서, 아래 깊은 복사를 위한 코드들이 의미가 있나 싶었는데 알고보니 clone() 내부적으로 객체를 복사해서 새로 생성하는 구조였다.
public class CloneHashCodeCheck {
static class Point implements Cloneable{
int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "Point{" + "x=" + x + ", y=" + y + '}';
}
@Override
public Object clone(){
Object obj = null;
try{
obj = super.clone();
}
catch (CloneNotSupportedException e){
e.printStackTrace();
}
return obj;
}
}
public static void main(String[] args) {
Point original = new Point(3, 5);
Point copy = (Point)original.clone(); // 복제
System.out.println(original);
System.out.println(copy);
System.out.println("==================");
System.out.println("original.hashCode(): "+ original.hashCode());
System.out.println("copy.hashCode(): "+copy.hashCode());
}
}
================== OUTPUT ==================
Point{x=3, y=5}
Point{x=3, y=5}
==================
original.hashCode(): 460141958
copy.hashCode(): 1163157884 // 다름을 확인할 수 있음.
0[a] == a[0]
과 함수를 포인터로 줄 수 있다는 건 정말 충격이었다.. 학부과정 내내 C언어를 쓰다보니까 잘알고 있다고 착각
을 했던 것 같다.. 반성해야지 부끄럽다.경험적
으로 이게 좋더라~ 하면서 이런 개념이 자리가 잡힌 것 같다.clone()
파트가 예전에 코드스쿼드 가입? 미션중에 루빅스 큐브를 풀 때 객체 배열을 하는 데 애먹었던 기억이 있어서 오늘 시간 투자를 많이했다. 몇가지 난해해서 좀 어려웠지만 프레디
한테 질문을 해서 힌트를 얻을 수 있었다. 덕분에 clone()을 지양해야하는 이유와 깊은복사의 여러가지 좋은 방법들 특히 복사 팩토리 메서드
방법은 너무 신기했고 앞으로 잘 써먹을 것 같다.