std :: function对象的成员函数和对象的生命周期 [英] std::function to member function of object and lifetime of object
问题描述
如果我有一个 std :: function
的实例绑定到对象实例的成员函数,并且该对象实例超出范围,否则将被销毁我的 std :: function
对象现在被认为是一个坏的指针,如果调用将失败?
If i have an instance of std::function
that is bound to a member function of an object instance and that object instance goes out of scope and is otherwise destroyed will my std::function
object now be considered to be a bad pointer that will fail if called?
示例:
int main(int argc,const char* argv){
type* instance = new type();
std::function<foo(bar)> func = std::bind(type::func,instance);
delete instance;
func(0);//is this an invalid call
}
在标准中有什么指定应该发生什么吗?我的预期是它会抛出和异常,因为对象不再存在
Is there something in the standard that specifies what should happen? My hunch is that it will throw and exception because the object no longer exists
编辑:
标准是否指定应该发生什么?
Does the standard specify what should happen?
是否未定义行为?
编辑2:
#include <iostream>
#include <functional>
class foo{
public:
void bar(int i){
std::cout<<i<<std::endl;
}
};
int main(int argc, const char * argv[]) {
foo* bar = new foo();
std::function<void(int)> f = std::bind(&foo::bar, bar,std::placeholders::_1);
delete bar;
f(0);//calling the dead objects function? Shouldn't this throw an exception?
return 0;
}
运行此代码,我接收到输出值0;
Running this code i receive an output value of 0;
推荐答案
会发生什么是未定义的行为。
What will happen is undefined behavior.
bind()
调用将返回包含 instance
,因此当你调用 func(0)
将有效地调用:
The bind()
call will return some object that contains a copy of instance
, so that when you call func(0)
will effectively call:
(instance->*(&type::func))(0);
参照无效指针,就像 instance
delete
d,是未定义的行为。
Dereferencing an invalid pointer, as you would do there if instance
were delete
d, is undefined behavior. It will not throw an exception (although, it's undefined, so it could, who knows).
请注意,你在调用中缺少一个占位符:
Note that you're missing a placeholder in your call:
std::function<foo(bar)> func =
std::bind(type::func, instance, std::placeholders::_1);
// ^^^^^^^ here ^^^^^^^^^
没有这个,你不能调用 func(0)
即使有一个未删除的实例。
Without that, you can't call func(0)
even with a non-deleted instance.
更新您的示例代码以更好地说明发生了什么:
Updating your example code to better illustrate what's going on:
struct foo{
int f;
~foo() { f = 0; }
void bar(int i) {
std::cout << i+f << std::endl;
}
};
使用添加的析构函数,可以看到复制指针> f )并复制指向的对象(在 g
):
With that added destructor, you can see the difference between copying the pointer (in f
) and copying the object that was pointed to (in g
):
foo* bar = new foo{42};
std::function<void(int)> f = std::bind(&foo::bar, bar, std::placeholders::_1);
std::function<void(int)> g = std::bind(&foo::bar, *bar, std::placeholders::_1);
f(100); // prints 142
g(100); // prints 142
delete bar;
f(100); // prints 100
g(100); // prints 142 still, because it has a copy of
// the object bar pointed to, rather than a copy
// of the pointer
这篇关于std :: function对象的成员函数和对象的生命周期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!