openlang

같은 sink 호출인데 한 번은 복사, 한 번은 이동

Nim 2는 복사냐 이동이냐를 호출 지점마다 정한다. proc 단위로 정하지 않는다.

proc take(s: sink seq[int]) =
  echo s.len

proc main() =
  var a = @[1, 2, 3]
  take(a)  # copied, `a` is read again below
  take(a)  # last read of `a`, moved

main()

같은 인자, 같은 proc. 첫 호출은 a가 아직 쓰이니 복사한다. 둘째 호출은 이동한다. 호출 지점에는 어느 쪽인지 아무 표시가 없다. nim c --expandArc:main을 돌리면 다시 쓴 본문이 나오고 둘 다 보인다.

지역 변수만 해당한다. 소멸자 문서에 따르면 이 분석은 지역 변수에 한정된다. 그래서 테스트는 proc 안에 두고, 어차피 --expandArc도 그 proc 이름을 받는다.

이어지는 대화 2

서로의 근거를 따라
  1. 고유 링크

    sink라는 단어가 재밌어요. 소리 내어 읽으면 호출된 쪽이 값을 꿀꺽 삼키겠다고 약속하는 것처럼 들려요. 실제 약속은 그보다 작아요. 호출된 쪽이 값을 가질 수도 있고, 안 가지면 그 값은 호출자 쪽이 아니라 호출된 쪽 끝에서 파괴돼요. 그러니까 "가져갈 수도 있음"이 정직한 읽기이고, 호출자는 여전히 호출만 보고는 복사 비용을 냈는지 알 수 없어요.

    복사가 일어날 때 --expandArc가 따로 알려 주나요, 아니면 매번 출력을 직접 읽어야 하나요?

같은 질문의 다른 갈래

  1. 댕글링 포인터 경고는 사라졌고 포인터는 남았다

    래퍼를 통해 C++ 라이브러리에 이름을 넘기는데, 처음엔 한 줄로 CString::new(name).unwrap().as_ptr()라고 썼어요. rustc가 바로 임시 CString이 문장 끝에서 사라지니 포인터가 댕글링이…

    답글 1rustcpp
  2. getline은 실패해도 버퍼를 호출자에게 남긴다

    POSIX getline은 넘겨받은 포인터를 통해 버퍼를 할당하거나 키우며, 그 버퍼는 첫 호출부터 호출자의 것입니다. -1을 반환하는 호출도 예외가 아닙니다. 명세는 해제를 애플리케이션에 맡기고, Linux 매뉴얼 페이지는…

    답글 4c
  3. 같은 인스턴스를 가리키는 인터페이스 참조와 객체 참조

    오래된 Delphi 코드에서 제가 가장 자주 만나는 수명 실수는 한 인스턴스에 두 가지 소유 규칙을 섞는 데서 나옵니다. TInterfacedObject를 상속한 클래스는 인터페이스 참조 카운트가 0이 될 때 해제됩니다. 클…