标准库中是否有C++等效于Rust的`std::mem::drop`?

9

std::mem::drop函数在Rust中移动其参数,然后通过超出作用域来销毁它。我尝试在C++中编写类似的函数,代码如下:

template <typename T,
          typename = std::enable_if_t<std::is_rvalue_reference<T &&>::value>>
void drop(T &&x) {
    T(std::move(x));
}

这个函数是否已经在标准库中存在?

编辑: 这个函数可以用来在作用域结束前调用对象的析构函数。考虑一个类,在销毁时关闭文件句柄,但不会在之前关闭。为了方便起见,假设ofstream没有一个close方法。你可以这样写:

ofstream f("out");
f << "first\n";
drop(move(f));
// f is closed now, and everything is flushed to disk

5
我不明白为什么你需要在C++中使用这样的东西。你使用它的用途是什么? - Baum mit Augen
据我所知,没有任何方法可以调用使得一个给定的变量在调用后无效。你是否可以改为使用代码块来实现?{ T x; } /* x超出范围 */ - Ry-
2
学习一门新语言时,有时需要使用不同的习惯用语。我无法想象出 drop 会在任何情况下与 C++ 的习惯用语相似。说实话,我想不出你为什么要使用它的一个理由。 - Edward Strange
1
我认为处理这种情况的C++惯用方式是从函数中返回。如果你无法从函数中返回,那么你的函数会做太多的事情。 - Mooing Duck
3
@CrazyEddie,你从来没有想过在作用域结束之前运行析构函数吗? - Shepmaster
@Shepmaster - 没有,我没有。 - Edward Strange
1个回答

8

C++标准库中没有这样的函数。不过,你可以使用这个习语来实现相同的效果:

SomeType var = ...;
//do stuff with `var`.
{auto _ = std::move(var);}
//The contents of `var` have been destroyed.

正如评论中指出的那样,C++缺乏Rust实际上“防止”您进一步使用var的能力。它的内容已经被移动了,但在C++中,它仍然是一个活的、有效的对象,你甚至可以通过适当地将其转换为一个明确定义的状态来重新使用它。
当然,这需要类型具有可移动构造性。一些类型,比如lock_guard就不具备这种属性,所以你在这方面有点麻烦。这意味着唯一关闭它的方法是使用它的内置接口。

2
“//var已被销毁。”其实并不是,你仍然可以对它进行赋值。此外,我仍然不知道这应该达到什么目的。 - Baum mit Augen
2
@BaummitAugen:它完成了对var所管理的任何内容的销毁。如果它是一个文件,那么文件就被关闭了。如果它是一个共享指针,引用计数将会减少。 - Nicol Bolas
2
@ BaummitAugen Nicol Bolas在现已删除的兄弟答案中说过这句话:“这个想法的重点是你有一个仍然在作用域内的堆栈变量,但你已经完成了使用它并希望清除对象。就像ifstream或其他一些东西,其中析构函数关闭文件。您不希望保持打开状态的时间比需要的时间长,但是将其堆分配只是为了能够重置它是愚蠢的。” - Shepmaster
1
@Shepmaster: "我想我有点想知道是否可以在函数参数上拥有“默认”的移动语义。" 不行,标准明确规定了要防止这种情况。问题中的11个字符是{auto _ = }字符。函数调用看起来像std::drop()。两种形式都需要std::move(),并且两种形式都需要一个分号。 - Nicol Bolas
1
@NicolBolas,我的问题在于,在Rust中,std::drop的作用不仅是运行时的,而且还是编译时的,因为如果你仍然使用变量,则编译器将明确报错。在C++中,同样的事情不会发生,但通过移植你给出的成语,你会产生相同的舒适感的错觉。在我看来,这显然是误导性的,很可能会被误用,特别是考虑到OP具有Rust背景的情况。 - HeroicKatora
显示剩余14条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接