kyaryunha   6년 전

먼저ㅓ 전 ㅓ 문제를 맞았지ㅣ만 왠지 다른 사람들 풀이도 궁금해서 풀이 줍줍하는 사람ㅁ..


아래 2개는 어떤ㄴ 존잘ㄹ님들의 코드//인데 짱 신기함ㅁ... 신기해서 모르는 부분 질문합니다(??)) 

뭔가ㅏ 코드 무단으로 가져와 질문하는 느낌ㅁ...인건 죄송합니다(??) 
출처는 첫번째는 쿠사가님의 코드고 두번째는 온조님의 코드입니다..!




lower_bound()... // 란 함수 자체를 저 코드 보면서 

처음 알게 된지라ㅏ...

인터넷 검색하다가 알게 된게 lower_bound는 주소값(??)을 반환하기 때문에 쓸 때 뒤에 주소값 빼줘야 
몇 번째 항목인지 알 수 있다고 하더라고요..!!! // 왠지 짱신기....

근데ㅔ.. 그극... 세번째 노란색 쳐놓은 곳에 왠지 프린트엪에 * 해놓는거 처음 보는... 
*가 무슨 용도인 건가요(?????????)

그냥ㅇ vx[lower_bound(v.begin(),v.end(),x[i])-v.begin()] 라 하는 것과 똑같은(??) 거려나요(??)


캡처.PNG


아래 코드...!!!! 왠지 structure  저렇게 정렬하는거 처음 본달까요??
//전 항상 f1함수 따로 만들어서 sort(arr,arr+n,f1) 이런식으로 하던지라.. 아니 사실 구조체 정렬을 최근에야 안건 사실ㄹ.. //신세계..
근데 그 [&] <--요거의 역할이 대체 무엇인가요(??????????)
포인터 할때 &만 쓰는것은 보아도 &에 []있는거 처음 알았어요..!! 근데ㅔ 이거 왠지 검색해도 안나옴.. 아시는 분 있다면 알려주시면 감사합니다..!
// 헉ㄱ 뭔가 sort 짱신기하다..... 저렇게 두가지 형태 말고 정렬하는 신기한 방법 또 있나요??


캡처2.PNG

++


#include <bits/stdc++.h>

요즘ㅁ 이 헤더파일 유행인가요(?????
코드 줍줍 할 때마다 다들 이거 쓰시는...!!

검색하니 나오는 글 왠지
http://tibyte.kr/260
https://gist.github.com/eduarc... 
이것 뿐....
뭔가 어렵다.. 코딩 시간 단축하려고 쓰이는 거라는데,... 대회(?)나가서 이거 써도 보통 되나요(??)
헤더파일을 모아놓은 헤더파일.. 이런 느낌이던데.. 썼을때 단점 같은것은 없으려나요..(??)



// 아 전 코드 줍줍은 보통ㅇ 풀어본 문제에 대해서 다른 풀이 찾을 때만합니다..!
// 혹은 레알ㄹ 한참 생각했는데도 제가 묭춍해서 못풀겠는데 풀이 궁금할때..// 꽤나 묭춍함 주의.. ...
// 좀 많은 제출량을 통해 입력데이터 다 때려맞춰서 if 정답? else 출력문 낸적은 한 번뿐이지만 있어도,
// 베껴 넣는 양심리스.....한 행동은 한적 없습니다..!


chogahui05   6년 전

a에 저장되어 있는 값이 106이라고 칩시다.

이건 주솟값입니다. *a의 의미는 a에 저장되어 있는 값이 106이므로 106번지에 가서 값을 얻어오라는 뜻입니다.

그러니까.

변수a 106 102번지

??       333 106번지

이런 식으로 저장이 되어 있다면 *a의 값은 333이 되겠죠.

kyaryunha   6년 전

@chogahui05
오오..!! 뭔가.... 신기하게 쓰이는 군요.. 주솟값을 저장하는 변수라니....
그런데 그냥 그 ??란 변수를 가져와다 쓰는게 이해하기 쉽고 더 편하지 않나요(??)
혹시 굳이 *를 쓰면... *이 귀여워서...는 아닌 것 같고.. 어떤 이점이 있나요(??)


djm03178   6년 전

포인터에 대해서 공부해 보시는 게 좋을 것 같습니다.

C와 C++에서 아주 중요한 개념이니 결국 언젠간 배우셔야 합니다.

kyaryunha   6년 전

@djm03178
헉.. 그렇군요... //왠지 포인터 어렵이..
혹시 *말고 위에 sort 질문할때 [&]도 포인터랑 관련있는 거려나요..?

chogahui05   6년 전

?? 란 변수를 써먹을 수 있으면 그냥 직접적으로 써먹는 게 편한데...
직접적으로 끌고 오지 못하는 경우도 있습니다.

포인터를 역참조 한다는 게..
주소가 가리키는 녀석 (아마도 객체)를 끌어오는 것이죠..

main 함수에 a가 있다고 해 봅시다. 그리고 b도 있다고 생각해 봅시다.

그런데 함수 f에서 main 함수에 있는 a와 b를 바꿔야 한다고 해 봅시다.

그럴 때 포인터 변수를 넘겨가지고 써먹을 수 있겠죠.. call by reference가 없어요. 무조건 값 복사. 

main 함수에 있는 a의 주소를 넘기고.. b의 주소를 넘겨서..


그런데 사실 이건 많이 써먹어 봐야.. 느끼는 것인지라..

chogahui05   6년 전

[&] 야는 람다식이에요. 관심 있으시면 찾아보세요.

kyaryunha   6년 전

어라.. 그러고보니 &랑 비슷하군요..!
&도 그런식으로 다른 함수에서 변수 부를때 쓰지 않던가요?..? //알고리즘 문제해결전략 책 dp코드들 보면 그런식으로 쓰는것 같던..

#include<stdio.h>
void f(int &a, int &b, int&c)
{
    c=a+b;
}
int main(void)
{
    int a,b,c;
    scanf("%d %d",&a,&b);
    f(a,b,c);
    printf("%d",c);
}

위에 이런 식으로..(???... // 그러고보니 *가 &랑 같은 거려나요..

근데.. 저 코드에서 &를 *로 바꾸면 돌아가지 않는군요.. 다른건가.. //포인터 어려워요 ㅠㅜ,ㅠ


chogahui05   6년 전

&가 레퍼런스 변수에요.

int aa;

즉 int &aa = a;

라고 한다면 a의 별명이 aa다. 뭐 이런 거죠.

그러니까 예를 또 들자면

int chokw;

int &chogahui = chokw;

라고 하면 chokw의 별명은 chogahui다.. 뭐 이런 뜻이 됩니다.

신기한 건 &chogahui의 값이나 &chokw의 값이 같다는 거죠. 그러니


저것도 마찬가지로 해석해 보면 main 함수의 a의 별명이 f 함수에서의 a네?

이기 땜시 뭐.. a랑 aa가 가리키는 공간이 같죠. 그러니 저래 써도 될 거구요.


질문. 함수에서 왜 &a를 *a로 바꾸면 안 돌아가느냐..

int형 포인터 변수하고 int형 변수는 type 자체가 다릅니다. 고로 안 돌아갑니다.

kyaryunha   6년 전

오오..!! &가 그런 의미였군요..!! //아무것도 모르고 그냥 사용했던..

알려주셔서 감사합니다..!! 

*....는 뭔가 어렵다..... 천천히 포인터 자세히 공부해봐야겠어요..!!

쨋든 뭔가 많이 알려주셔서 감사합니다//!

chogahui05   6년 전

그건 아직 메모리 그림이 아직 잘 안 그려져서 그래요..

천천히 그려보시다 보면 언젠가는 조금씩 아시게 될 거에요..

doju   6년 전

Lambda 함수는 쉽게 말해서 한 번 쓰고 버리는 이름 없는 함수이며, C++11에서 추가된 문법입니다.

Lambda 함수에서는 함수 내부에서 함수 외부의 변수들을 가져다 쓸 수 있습니다. 이를 capture라고 하고, capture 규칙을 질문에 있는 코드와 같이 대괄호 안에 표시합니다.
[&]는 Lambda 함수 내부에서 외부의 변수들을 가져다 쓸 때 항상 레퍼런스 변수로 가져다 쓰겠다는 뜻입니다. 쉽게 말해서 함수 내부에서 함수 외부의 변수의 값을 변경할 수 있습니다.

그 외에

  • []: 외부 변수를 전혀 사용하지 않음
  • [=]: 외부 변수를 참조만 하고 값을 바꾸지 않음
  • 원하는 변수들만 따로 지정할 수도 있고, 변수와 기본 규칙을 섞어 쓸 수도 있음 - [a, &b], [&a, =], [&, b]

등의 사용법이 있습니다. capture를 제외한 문법은 일반적인 함수와 거의 동일합니다.

cppreference.com - Lambda expressions


<bits/stdc++.h>는 링크하신 첫 번째 블로그 글에 적혀 있듯이 C++ 표준 헤더파일은 아닙니다. 즉 환경에 따라서는 지원하지 않을 수도 있습니다. 경험상 gcc/g++ 기반의 환경에서는 대부분 지원하는 것 같습니다.

표준으로 보장되어 있지 않기 때문에 환경에 따라서 지원하지 않거나 내용이 다를 수도 있다는 점이 큰 단점으로, C++ 라이브러리에 충분히 숙달되지 않은 상태로 저 헤더파일에 의존하게 된다면 저 헤더파일이 지원되지 않는 상황에 처했을 때 곤란해질 수 있습니다.
예를 들어 <bits/stdc++.h>에 의존해서 lower_bound를 써 왔는데, 대회 채점 환경이 저 헤더파일을 지원하지 않고 lower_bound<algorithm>에 선언되어 있다는 것도 모른다면 크게 당황하겠죠.

저는 자주 쓰는 라이브러리들에 익숙해졌더니 오히려 저걸 쓸 필요를 딱히 못 느껴서 안 쓰는데, 취향 차이일 것 같습니다.


남의 코드를 많이 읽는 것은 좋은 습관이라고 생각합니다 :) 한 문제를 풀더라도 실행 속도가 더 빠른 코드, 메모리를 덜 쓰는 코드, 더 짧은 코드들을 보고 분석하고 풀이가 틀렸다는 것을 증명하고 반례를 만들고 하다 보면 더 많은 것을 얻어 갈 수 있는 것 같아요.

isku   6년 전

좋은 질문과 고수님들의 답변, 멋지고 재미있네요.

많이 배워갑니다 ^_^

kyaryunha   6년 전

자세한 설명 감사합니다 :)
오 뭔가 [](){}()... 신기한 구조네요...

뭔가 {}안쪽에 printf x 했더니 4 출력하는..
첫 번째 () 안쪽의 변수들에, 마지막 ()안쪽의 변수들의 값을 차례 대로 넣는다는 뜻이려나요??

+

int f(){ int kk; }
int main(void)
{
    [&](int x){
        //여기서 저쪽 아예 다른 함수에 있는 kk 데려온다면 
    }
}

혹시 이런식으로 아예 저쪽 지역변수에서 캡쳐해 오는 것도 가능한가요(??) 아니면 범위가 그래도 좀ㅁ 같은 {} 안에서만 캡쳐 가능한건가요(??




doju   6년 전

위의 코드는 아래의 Code 1 과 (표면적으로) 같은 일을 합니다. 비교해 보세요.

Lambda 함수가 쓰이는 위치에서 참조할 수 있는 변수만 capture할 수 있습니다. 설령 같은 괄호 안이더라도 Lambda 함수보다 나중에 선언된 변수 역시 capture 불가능합니다(Code 2).

kyaryunha   6년 전

아아 뒤에 ()는 그냥 함수 호출한 것이었군요..!! // 바로 호출할 수 있군요 깨닫..!

헉ㄱ 좋은 코드 예시들 덕분에 잘 이해됬어요..!

알려주셔서 감사합니다 :)

kyaryunha   6년 전

혹시ㅣ..!! 어젯밤에 계속 궁금하던 내용인데요..! //그치만 밤엔 컴이 없어서 질문을 못하던..

뭔가 람다식으로는 탑다운디피..그런 재귀함수 못돌리나요(?????
뭔가 return의 자료형이 무엇인지 지정해주는 곳이 없으니깐..... 

그리고 굳이 return 값 없더라도 람다식 안에서, 자기 자신 호출하는 것도 안되려나요(???))


엥 근데ㅔ 람다식 제가 맨 위에서 주워온 코드에서 노란색 줄쳐놓은 부분 보면 return  하는데 그러면 리턴값은 있어도 상관 없는듯 한데.... 리턴 값의 자료형을 따로 지정해주지 않아도 auto처럼 알아서 해주는 거려나요.(?....


쨋든... 혹시 람다함수 리턴이랑 자기 자신 재호출ㄹ 그런거 어떻게 돌아가는 건지 아신다면 설명해주실수 있으신가요..! +ㅁ+

doju   6년 전

Lambda 함수에 이름을 붙이고 자기 자신을 capture한 뒤 function wrapper로 감싸면 일반 함수처럼 사용할 수 있고 재귀 호출 역시 가능합니다.
cppreference.com - std::function

Lambda 함수의 리턴 타입은 auto와 같은 방법으로 컴파일러가 알아서 추론하며, 리턴 타입을 명시해 줄 수도 있습니다(위의 답변에 있는 레퍼런스 문서의 2번 syntax).

Lambda 함수라는 키워드만 알면 관련된 내용들은 직접 검색하는 편이("c++ recursive lambda function", "c++ lambda return type" 등) 더 많은 정보를 빠르게 얻을 수 있으니 남은 궁금증은 직접 해결해 보시기 바랍니다. 워낙 사용법이 다양하고 C++ 버전이 올라가면서 세세한 문법이 계속해서 바뀌고 있기 때문에 제가 계속 답변드릴 수는 없을 것 같네요.

kyaryunha   6년 전

알려주셔서 감사합니다...!!! :)

댓글을 작성하려면 로그인해야 합니다.