단순 복사 회피용 전달일 때
void foo_with_ref(const string &ref);
void foo_with_ptr(string *ptr);
foo_with_ref("ASDF"); // OK
foo_with_ptr("ASDF"); // 노답
string str = "wer";
foo_with_ref(str); // OK
foo_with_ptr(str); // OK
foo_with_ref(nullptr); // 노답
foo_with_ptr(nullptr); // OK
포인터로 전달받으면 optional이 가능하다.
레퍼런스로 전달받으면 rvalue도 받을 수 있다.
넘겨줘서 값이 변경될 때
struct pig{
int a,b,c,d;
};
void foo_with_ref(pig &ref){
pig.a = 33;
}
void foo_with_ptr(pig *ptr){
ptr->a = 33;
}
pig p;
foo_with_ref(p); // OK, 하지만 &없이 넘겨줬는데 값이 변해버리는건 가끔 사용자로 하여금 당황스러움을 만들어낼 수 있다.
foo_with_ptr(&p); // OK
void get_xy(int *x,int *y);
void get_xy(int &x,int &y);
int x;
get_xy(&x, nullptr); // OK, 원한다면 x만 받아오도록 만들 수 있다.
get_xy(&x, ???); // 노답
리턴할 때
string &foo_with_ref(){
string result = "hello";
return result; // 노답
}
string *foo_with_ptr(){
string *result = new string("hello");
return result; // OK
}
class foo{
const string &get_name() const{ // OK
return name;
}
private:
string name;
};
이 경우에는 foo::get_name이 불릴 동안 항상 name이 살아있는게 보장되니 레퍼런스를 리턴해도 괜찮다.
(STL 컨테이너에서도 내부 값을 반환할 때 레퍼런스 반환을 수행한다. http://www.cplusplus.com/reference/vector/vector/operator[]/)
class foo{
string *get_name() const{ // OK
return &name;
}
private:
string name;
};
일단은 정상적인 코드지만, 만들고자 했던 것은 get_name_ptr이 아니라 get_name이다, 굳이 포인터를 리턴하면 이상해진다.
또한 사용자 입장에서 포인터를 리턴받앗을 때 포인터의 관리를 foo가 하는지, 자신이 해야하는지 알수가 없으므로 반드시 가이드해야 한다는 추가적인 공수가 필요하다.