C++ 将 std::bind 与成员函数一起使用,是否为此参数使用对象指针?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15264003/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:13:10  来源:igfitidea点击:

Using std::bind with member function, use object pointer or not for this argument?

c++c++11language-lawyer

提问by Some programmer dude

When using std::bindto bind a member function, the first argument is the objects thispointer. However it works passing the object both as a pointer and not.

当使用std::bind结合一个成员函数,所述第一参数是对象this的指针。但是,它既可以将对象作为指针传递,也可以不传递。

See for example the following program:

例如,请参阅以下程序:

#include <iostream>
#include <functional>

struct foo
{
    void bar(int v) { std::cout << "foo::bar - " << v << '\n'; }
};

int main()
{
    foo my_foo;

    auto f1 = std::bind(&foo::bar, my_foo, 1);
    auto f2 = std::bind(&foo::bar, &my_foo, 2);

    f1();
    f2();
}

Both clang and GCC compiles this without complaints, and the result works for both binds:

clang 和 GCC 都毫无怨言地编译了这个,结果对两个绑定都有效:

foo::bar - 1
foo::bar - 2

I have been trying to wrap my head around the specification (section 20.8.9) but it's one of the places where it's far from clear to me.

我一直试图围绕规范(第 20.8.9 节)进行思考,但这是我对它很不明确的地方之一。

Should only one be correct, or are both correct?

应该只有一个正确,还是都正确?

采纳答案by Daniel Frey

Both are correct. 20.8.9.1.2 forwards to 20.8.2 to describe the requirements and the effect of your call to bind. 20.8.2 is:

两者都是正确的。20.8.9.1.2 转至 20.8.2 描述您调用 的要求和效果bind。20.8.2 是:

20.8.2 Requirements [func.require]

1Define INVOKE(f, t1, t2, ..., tN)as follows:

(t1.*f)(t2, ..., tN)when fis a pointer to a member function of a class Tand t1is an object of type Tor a reference to an object of type Tor a reference to an object of a type derived from T;

((*t1).*f)(t2, ..., tN)when fis a pointer to a member function of a class Tand t1is not one of the types described in the previous item;

t1.*fwhen N == 1and fis a pointer to member data of a class Tand t1is an object of type Tor a reference to an object of type Tor a reference to an object of a type derived from T;

(*t1).*fwhen N == 1and fis a pointer to member data of a class Tand t1is not one of the types described in the previous item;

f(t1, t2, ..., tN)in all other cases.

20.8.2 需求 [func.require]

1定义INVOKE(f, t1, t2, ..., tN)如下:

(t1.*f)(t2, ..., tN)whenf是指向类成员函数的指针,T并且t1是类型T对象T或对类型对象的引用或对派生自 类型的对象的引用T

((*t1).*f)(t2, ..., tN)whenf是指向类成员函数的指针,T并且t1不是上一项中描述的类型之一;

t1.*fN == 1f是指向类成员数据的指针,T并且t1是类型对象T或类型对象的T引用或从 派生的类型对象的引用时T

(*t1).*fN == 1f是指向类成员数据的指针,T并且t1不是上一项中描述的类型之一;

——f(t1, t2, ..., tN)在所有其他情况下。

The first two options allow both a reference and a pointer.

前两个选项允许引用和指针。

The important thing to notice here is that the wording does notlimit you to plain pointers. You could use a std::shared_ptror some other smart pointer to keep your instance alive while bound and it would still work with std::bindas t1is dereferenced, no matter what it is (given, of course, that it's possible).

这里要注意的重要一点是,措辞也不会限制你普通指针。你可以使用一个std::shared_ptr或一些其他的智能指针,让您的实例还活着,而约束,它会仍然工作std::bind作为t1被废弃时,不管它是什么(因为,当然,这是可能的)。

回答by rytis

To add to the correct answer (that both forms are allowed).

添加到正确答案(允许两种形式)。

I think of the two binding options in analogy with function argument declaration, which may be "passed by value" or "passed by reference".

我认为这两个绑定选项与函数参数声明类似,可以“按值传递”或“按引用传递”。

In the case of f1(aka passing my_foo"by value") the result doesn't "see" any changes made to my_foopast the binding point. This may not be desired especially if my_fooevolves. "By value" binding has an additional "cost" of (several) calls to a copy constructor.

f1(又名my_foo“按值”传递)的情况下,结果不会“看到”my_foo超过绑定点所做的任何更改。这可能不是我们所希望的,尤其是在my_foo进化的情况下。“按值”绑定具有对复制构造函数的(多次)调用的额外“成本”。

回答by devotee

There is a difference. As rytis put forward, passing by value doesn't see the changes made to my_foo. For example, in case my_foo is a class, passing by value doesn't see a change made to a member data of my_foo.

它们是有区别的。正如 rytis 所提出的,按值传递不会看到对 my_foo 所做的更改。例如,如果 my_foo 是一个类,则按值传递不会看到对 my_foo 的成员数据所做的更改。