此问题与this answer中的DelayedCaller有关。
DelayedCaller绑定一个函数指针及其参数,并且就像一个魅力一样,只要参数不是指向比DelayedCaller执行更短寿命的指针(认为局部变量的string.c_str()作为参数)
为了避免这个问题,我为扫描参数的模板函数处理的有问题的参数创建了一个存储空间。
我现在需要的是相反的结果:我希望通过将给予DelayedCaller的指针的地址作为参数进行评估,在同一类型的不同对象上调用成员函数。
我目前看到两种方法:
我赞成2.超过1.(我不想在使用call()时提供参数),但是我甚至没有考虑其他选项。
示例:
#include <iostream>
#include <string>
#include <functional>
#include <memory>
class MyClass
{
float myFloat;
public:
MyClass(float f):myFloat(f){}
void myFunc(int arg1)
{
std::cout << arg1 << ", " << myFloat << '\n';
}
};
class MyContainer
{
public:
MyClass* object;
};
// DelayedCaller implementation
class DelayedCaller
{
public:
template <typename TFunction, typename... TArgs>
static std::shared_ptr<DelayedCaller> setup(TFunction&& a_func,
TArgs&&... a_args)
{
return std::shared_ptr<DelayedCaller>(new DelayedCaller(
std::bind(std::forward<TFunction>(a_func),
std::forward<TArgs>(a_args)...)));
}
void call() const { func_(); }
private:
using func_type = std::function<void()>;
DelayedCaller(func_type&& a_ft) : func_(std::forward<func_type>(a_ft)) {}
func_type func_;
};
int main()
{
MyContainer container;
MyClass* c1 = new MyClass(45.6);
container.object = c1;
// the next line is the critical one. Instead of myFunc being called
// on the current value of container.object, it should be called on
// the one container.object is holding when caller is called.
auto caller(DelayedCaller::setup(&MyClass::myFunc, container.object, 123));
caller->call();
MyClass* c2 = new MyClass(22.8);
container.object = c2;
caller->call();
delete c1;
delete c2;
return 0;
}
答案 0 :(得分:0)
如何离开&#34;绑定&#34;使用lambda表达式的C ++编译器?
auto caller(DelayedCaller::setup([&container] { container.object->myFunc(123);}));
给出输出:
123, 45.6
123, 22.8
PS。这个lambda可以直接转换为std::function<void(void)>
,因此DelayedCaller
构造函数可以是公共的,如果需要,可以在没有setup
函数的情况下创建。如果你可以编辑它的实现当然。
答案 1 :(得分:0)
std::reference_wrapper
可能会有所帮助,请使用:
auto caller(DelayedCaller::setup(&MyClass::myFunc, std::ref(container.object), 123));
答案 2 :(得分:0)
你真的需要了解std :: bind的作用。
当使用std :: bind时,它将复制(或分别移动它们分别是r值,但作为提醒,它们是否被移动依赖于可调用对象,每个参数都被输入到std ::分别绑定)
接下来,我将讨论当只有一个参数时的情况,但它的规则适用于分别存在多个参数的情况。
可调用对象(可能是函数或函子的指针)和std :: bind返回的std :: function对象的参数,所以在你问的情况下它永远不会出现。
如果参数不是指针或引用,您可以将(临时)对象提供给sts :: bind,而c ++标准承诺只会复制或移动它,而不是通过引用,除非你使用std :: ref或std :: cref来包装那个对象。
但是如果你提供std :: unique_ptr或包装指针的其他东西(或如上所示的引用),你需要将它们视为指针(引用),而不是对象(尽管复制/移动选择仍然发生)
如果参数是指针,那么指针将被复制到其中。
在这种情况下,如果指针指向局部变量bingo,那么你有一个要跟踪的bug。
实际上你编写的代码如果(对象的析构函数不会对内存中的对象造成任何损害,换句话说,对象在被破坏后存在,如POD等) )&amp;&amp; (内存中包含的对象不被任何其他对象重用,当这样的时候(另一个函数被调用,其局部变量占用该对象的内存并向其写入内容)发生它被重用)。
如果指针指向你在堆上分配的并且在你完成对DelayedCaller :: cal的调用之前它没有被释放,那么你的代码没有任何问题。
如果指针是一个指向文字的常量指针,那么一切都会好的。
参数是引用的情况与它是指针的情况大致相同。