당신이 확실하게 말을 의미하는 "첫번째 인수가 참조입니다"라고 "첫번째 인수가 포인터입니다 ": &
연산자는 객체의 주소를 가져와 포인터를 생성합니다.
이 질문에 대답하기 전에, 잠시 한 걸음 뒤로 물러나 당신이 기능을 제공
std::bind(my_divide, 2, 2)
를 사용할 때 std::bind()
의 첫 번째 사용 살펴 보자. 어떤 함수가 전달되면 포인터로 쇠퇴합니다.상기 식 명시 std::bind()
의 첫번째 인자는 함수를 호출하는 방법을 식별 목적 어드레스
std::bind(&my_divide, 2, 2)
복용 이것과 동등하다. 위의 경우에는 double(*)(double, double)
유형의 함수에 대한 포인터입니다. 적절한 함수 호출 연산자를 사용하는 다른 호출 가능 객체도 마찬가지입니다.
구성원 함수는 매우 일반적이므로 std::bind()
은 멤버 함수에 대한 포인터를 처리 할 수 있도록 지원합니다. &print_sum
을 사용하면 멤버 함수에 대한 포인터 즉, void (Foo::*)(int, int)
유형의 엔티티를 얻을 수 있습니다. 함수 이름은 암시 적으로 함수에 대한 포인터로 붕괴되지만 즉, &
은 생략 될 수 있지만 멤버 함수 (또는 데이터 멤버)에 대해서는 동일하지 않습니다. 멤버 함수에 대한 포인터를 얻으려면 함수를 사용할 필요가 있습니다. &
.
구성원에 대한 포인터는 class
에만 해당하지만 클래스의 모든 개체와 함께 사용할 수 있습니다. 즉, 특정 개체와 독립적입니다. C++은 멤버 함수를 직접적으로 객체에 바인딩하는 직접적인 방법이 없습니다 (C#에서는 적용된 멤버 이름을 가진 객체를 사용하여 객체에 직접 바인딩 된 함수를 얻을 수 있다고 생각하지만 이후 10 년 이상이 걸립니다). 나는 마지막으로 C# 비트를 프로그래밍했다.)
내부적으로, std::bind()
은 멤버 함수에 대한 포인터가 전달되었음을 감지하고이를 호출 가능 객체 (예 : std::mem_fn()
)의 첫 번째 인수와 함께 호출 할 가능성이 높습니다. non-static
멤버 함수는 객체를 필요로하기 때문에, 호출 가능한 호출 가능한 객체의 첫 번째 인수는 해당 클래스의 객체에 대한 참조 또는 [스마트] 포인터입니다.
멤버 함수에 대한 포인터를 사용하려면 객체가 필요합니다. std::bind()
이있는 멤버에 대한 포인터를 사용하는 경우 std::bind()
의 두 번째 인수는 객체가 언제오고 있는지 지정해야합니다. 하여 예
std::bind(&Foo::print_sum, &foo, 95, _1)
에서 생성 된 호출 객체 사용 &foo
, 즉 대상이 foo
(타입 Foo*
)에 대한 포인터. std::bind()
은 포인터처럼 보이는 것을 사용하기에 충분히 똑똑하고, 적절한 유형의 참조 (예 : std::reference_wrapper<Foo>
)로 변환 가능한 것 또는 첫 번째 인수가 멤버에 대한 포인터 인 경우 객체의 [copy] 객체를 사용할 수 있습니다.
나는 당신이 회원에 대한 포인터를 본 적이 없다고 생각합니다. 그렇지 않으면 매우 명확합니다. apply()
단순히 두 Foo
객체에 대한 포인터와 멤버 함수에 대한 포인터를 가져옵니다
#include <iostream>
struct Foo {
int value;
void f() { std::cout << "f(" << this->value << ")\n"; }
void g() { std::cout << "g(" << this->value << ")\n"; }
};
void apply(Foo* foo1, Foo* foo2, void (Foo::*fun)()) {
(foo1->*fun)(); // call fun on the object foo1
(foo2->*fun)(); // call fun on the object foo2
}
int main() {
Foo foo1{1};
Foo foo2{2};
apply(&foo1, &foo2, &Foo::f);
apply(&foo1, &foo2, &Foo::g);
}
기능 : 다음은 간단한 예입니다. 각 객체가 가리키는 멤버 함수를 호출합니다. 이 재미있는 ->*
연산자는 개체에 대한 포인터에 멤버에 대한 포인터를 적용하고 있습니다. 또한 멤버에 대한 포인터를 객체에 적용하는 .*
연산자가 있습니다 (또는 객체와 마찬가지로 동작하므로 객체에 대한 참조). 멤버 함수에 대한 포인터는 객체를 필요로하기 때문에, 객체를 요청하는이 연산자를 사용할 필요가 있습니다. 내부적으로는 std::bind()
이 발생합니다.
두 개의 포인터와 함께 apply()
이 호출되고 &Foo::f
이 호출되면 해당 개체에 f()
구성원이 호출 될 때와 완전히 동일하게 작동합니다.마찬가지로 두 포인터를 사용하여 apply()
을 호출하고 &Foo::g
을 호출하면 해당 객체에서 g()
이라는 멤버가 호출 될 때와 완전히 동일하게 작동합니다 (의미 론적 동작은 동일하지만 컴파일러에서 함수를 인라인하는 데 더 많은 시간이 소요될 수 있으며 일반적으로 실패합니다). 회원에 대한 포인터가 관련되어있을 때 그렇게 함).
식별자 뒤에 '&'가 오는 것은 "참조"를 의미하지 않습니다. 변수를 선언하지 않는 한,'&'앞에는 typename이옵니다. 식별자에'&'가 적용되면 포인터 *가 생깁니다. –
일반적으로'std :: bind'를 사용하지 마십시오. 그것은 당신이 기본을 마스터 한 후에도 놀라운 결과를 만들어내는 정말 깊은 단점이 있습니다. 나는 그럴 가치가 없다는 것을 안다. – Yakk