예를 들어서
ofstream os; ofstream os2; os2 = os;
같이 쓰면 3번째 줄의 대입 연산에서 에러가 발생합니다. 에러가 발생하는 이유와 대안이 있다면 알고 싶습니다.
가장 간단한 방법은 참조로 전달하는 것입니다.
ofstream os; ofstream &os2 = os;
이는 기본적으로 C++에서 stream은 복사가 불가능한 객체이기 때문이고, 그렇게 만든 이유는 stream이라는 게 원래 입출력 device를 추상화한 개념이기 때문일 겁니다. 아마도. 예컨대 ofstream 객체를 복사한다면 그 대상이 되는 파일도 복사되어 두 개가 되어야 할 텐데, 그렇게 할 수가 없잖아요?
그래서 스트림은 거의 항상 참조로 주고받으며 사용합니다.
Modern C++ 사용에 거부감이 없는 사람이라면, 내가 다시 쓸 일이 없는 ofstream 객체를 넘겨주기 위해 move semantic을 쓸 수도 있겠지요.
ofstream os; ofstream os2 = std::move(os);
하지만 사실 함수에 stream을 전달해줘야 하는 경우 보통 쓰이는 방법은 ostream &으로 전달하는 겁니다. 다형성도 활용할 겸.
상당히 많은 사람들이 Modern C++ 사용에 거부감이 있더라구요. "스마트포인터 없이도 10년 동안 프로그래밍 잘 해 왔다" 고 당당히 말하는 사람도 많습니다.
스마트 포인터는 종종 사용하기 좀 미묘한 상황이 생기는 경우가 있단 말이죠...
예컨대 tree 자료 구조를 만든다고 합시다.
1) parent node가 child node를 가리키게 하고 싶은데, 모든 child는 단 하나의 parent를 가지므로 unique_ptr를 쓰는 게 좋은 선택일 듯 합니다.
하지만 정작 그렇게 만들어 놓고 나면, tree를 traversal한다던가 하는 등 tree node에 대한 포인터를 잠시 따로 만들어서 사용하기 까다롭습니다. unique_ptr는 복사가 안되니까요.
결국 (1) unique_ptr에 대한 포인터를 얻어서 사용하거나 (2) get을 호출해서 raw point를 받아다 쓰는 수밖에 없지요.
어떤 방법이 더 낫다고 생각하십니까? 개인적으로 저는 둘 다 썩 기분 좋은 해결책은 아닌 것 같습니다만.
2) 애초에 parent가 child를 shared_ptr로 가리키게 만드는 게 더 좋은 선택이었을지도 모르죠.
그런데 이 경우 reference counting을 위한 (거의 불필요한) 메모리 오버헤드가 발생하기도 하고, shared_ptr의 경우 그 조작이 thread-safe해야 한다는 조건이 붙어 있어서 그로 인한 성능 오버헤드도 발생합니다.
솔직히 말하면 저는 그 overhead가 실제로 뭐 얼마나 되겠어 싶은 입장이긴 한데, 이게 신경쓰이는 분들은 또 shared_ptr는 스레드 사이에서 객체를 공유하는 경우가 아니면 피하라고 조언할 정도라고 하니까요. -_-;;
아무튼 뭐 그렇습니다. 물론 Modern C++가 너무 빠르게 변화하다 보니 따라가기가 벅차서, 혹은 어려운 언어를 어렵게 사용하는 데 자부심을 가지시는 분도 있겠습니다. 각자 나름의 이유가 있겠지요.
======
그런데 다른 건 몰라도 move semantic은 진짜 잘 추가된 것 같습니다.
내부구조 뜯어보면 달랑 포인터 하나가 거의 전부인 클래스 (vector 등), 값싸게 옮길 방법이 없어서 포인터나 레퍼런스로 전달하던 시절 기억하십니까? 전 이제 기억이 가물가물하네요.
그 밖에도 C++03엔 당연히 있어야 했던 것들이 없어서 삽질하게 만들었던 요소들이 여럿 있었지요.
감사합니다. 궁금했던 내용은 물론이고 관련된 지식까지 많이 도움이 되었습니다.
가장 간단한 방법은 참조로 전달하는 것입니다.
가장 간단한 방법은 참조로 전달하는 것입니다.
이는 기본적으로 C++에서 stream은 복사가 불가능한 객체이기 때문이고,
그렇게 만든 이유는 stream이라는 게 원래 입출력 device를 추상화한 개념이기 때문일 겁니다. 아마도.
예컨대 ofstream 객체를 복사한다면 그 대상이 되는 파일도 복사되어 두 개가 되어야 할 텐데, 그렇게 할 수가 없잖아요?
그래서 스트림은 거의 항상 참조로 주고받으며 사용합니다.
++
Modern C++ 사용에 거부감이 없는 사람이라면, 내가 다시 쓸 일이 없는 ofstream 객체를 넘겨주기 위해 move semantic을 쓸 수도 있겠지요.
하지만 사실 함수에 stream을 전달해줘야 하는 경우 보통 쓰이는 방법은 ostream &으로 전달하는 겁니다. 다형성도 활용할 겸.
상당히 많은 사람들이 Modern C++ 사용에
상당히 많은 사람들이 Modern C++ 사용에 거부감이 있더라구요.
"스마트포인터 없이도 10년 동안 프로그래밍 잘 해 왔다" 고 당당히 말하는 사람도 많습니다.
스마트 포인터는 종종 사용하기 좀 미묘한 상황이
스마트 포인터는 종종 사용하기 좀 미묘한 상황이 생기는 경우가 있단 말이죠...
예컨대 tree 자료 구조를 만든다고 합시다.
1) parent node가 child node를 가리키게 하고 싶은데, 모든 child는 단 하나의 parent를 가지므로 unique_ptr를 쓰는 게 좋은 선택일 듯 합니다.
하지만 정작 그렇게 만들어 놓고 나면, tree를 traversal한다던가 하는 등 tree node에 대한 포인터를 잠시 따로 만들어서 사용하기 까다롭습니다. unique_ptr는 복사가 안되니까요.
결국 (1) unique_ptr에 대한 포인터를 얻어서 사용하거나 (2) get을 호출해서 raw point를 받아다 쓰는 수밖에 없지요.
어떤 방법이 더 낫다고 생각하십니까? 개인적으로 저는 둘 다 썩 기분 좋은 해결책은 아닌 것 같습니다만.
2) 애초에 parent가 child를 shared_ptr로 가리키게 만드는 게 더 좋은 선택이었을지도 모르죠.
그런데 이 경우 reference counting을 위한 (거의 불필요한) 메모리 오버헤드가 발생하기도 하고, shared_ptr의 경우 그 조작이 thread-safe해야 한다는 조건이 붙어 있어서 그로 인한 성능 오버헤드도 발생합니다.
솔직히 말하면 저는 그 overhead가 실제로 뭐 얼마나 되겠어 싶은 입장이긴 한데, 이게 신경쓰이는 분들은 또 shared_ptr는 스레드 사이에서 객체를 공유하는 경우가 아니면 피하라고 조언할 정도라고 하니까요. -_-;;
아무튼 뭐 그렇습니다. 물론 Modern C++가 너무 빠르게 변화하다 보니 따라가기가 벅차서, 혹은 어려운 언어를 어렵게 사용하는 데 자부심을 가지시는 분도 있겠습니다. 각자 나름의 이유가 있겠지요.
======
그런데 다른 건 몰라도 move semantic은 진짜 잘 추가된 것 같습니다.
내부구조 뜯어보면 달랑 포인터 하나가 거의 전부인 클래스 (vector 등), 값싸게 옮길 방법이 없어서 포인터나 레퍼런스로 전달하던 시절 기억하십니까? 전 이제 기억이 가물가물하네요.
그 밖에도 C++03엔 당연히 있어야 했던 것들이 없어서 삽질하게 만들었던 요소들이 여럿 있었지요.
감사합니다. 궁금했던 내용은 물론이고 관련된 지식까지
감사합니다. 궁금했던 내용은 물론이고 관련된 지식까지 많이 도움이 되었습니다.