【发布时间】:2020-07-17 13:02:44
【问题描述】:
在另一个问题下的cmets中,有人说一个常见的错误是:
在调用
std::function时调用它会导致销毁持有它的对象
虽然在健壮的代码中显然可以避免这样做的“危险”事情,但它真的是错误的吗?我在标准中找不到任何可以确保:
-
std::function不得被其目标可调用对象销毁 -
std::function的生命周期不得在其目标可调用对象执行期间结束 - 函子的生命周期通常不能在其执行期间结束
据我所知,执行以下操作是合法且定义明确的(尽管品味不佳):
struct Foo
{
void baz()
{
delete this;
// Just don't use any members after this point
}
};
int main()
{
Foo* foo = new Foo();
foo->baz();
}
这表明,在没有任何压倒一切的限制(我无法找到)的情况下,以下内容也将是技术上明确定义的:
#include <functional>
struct Bar
{
std::function<void()> func;
};
int main()
{
Bar* bar = new Bar();
bar->func = [&]() { delete bar; };
bar->func();
}
不是这样吗?如果不是,哪个措辞禁止?
(对于奖励积分,如果这与以前的标准相比有所改变,那将会很有趣。)
【问题讨论】:
-
@StoryTeller-UnslanderMonica 我不知道;标准says nothing about any "internal state object" 或其他任何东西;只有目标被调用。而已。如果一个实现选择做其他事情,那肯定是该实现冒昧,而不是似乎遵守规则的功能用户!因此,我认为本案不属于“措辞中未指明,故为UB”的范畴;我认为,在最好的情况下,实现会施加额外的要求/约束。
-
我已经看到对象有
if (self_destruct) delete this;,这似乎是一样的。似乎也很差劲,但我希望合法,因为我项目的代码库中有很多。 -
可能属于“实现定义”的行为。如果标准中没有任何内容说明您可以或不能在函数对象执行时销毁它,那么听起来它可以解释要走哪条路。
-
@1201ProgramAlarm 如果是这样,那将是 UB(根据我的回忆,实现定义必须由标准明确规定)。但是,如上所述,我不相信这属于这一类。这就像说使用
bool是UB,因为标准没有告诉我们在吃意大利面时是否可以这样做。如果作为程序员,您满足函数调用的所有先决条件,那么您应该能够期望得到明确定义的结果。而且,根据我对链接段落的阅读,这就是这个假设的糟糕程序员所做的一切。
标签: c++ c++17 language-lawyer