在C ++中,如果我写
token make_token() { return token{}; }
然后按如下方式使用
void use_token()
{
make_token();
// extra code
}
没有为变量分配令牌,token
的析构函数会在执行额外代码之前触发。如何让析构函数只在函数结束时触发而不必创建变量?
注意:我想完全避免制作变量。我知道我可以做auto& t = make_token()
或类似的事情,但我想通过返回 (我不知道是什么)来解决这个问题并没有解决这个问题立即
为什么我想要这个:基本上,在我的应用程序(编程语言的编译器)中,我将这些东西称为令牌。令牌的构造函数可以放置{
和缩进,然后它的析构函数可以放置}
并取消缩进。我认为设置按值返回这些标记的函数是个好主意,但我实际上并不想将它们分配给任何值,因为标记是无用的并且没有函数。
为了减轻混淆,我的token
不是一个词法令牌。我使用工作token
代替工作cookie
。它意味着在构造函数中执行某些操作,等到其作用域结束,然后在其析构函数中执行某些操作。就是这样。顺便说一下,如果我用C#写这个,我会写类似
using (make_token())
{
// my code here
}
它会按预期工作。但事实证明,在C ++中很难做到这么简单。
答案 0 :(得分:8)
是。您可以使用常量引用。这在C ++中被称为最重要的const ,它是一个并不广为人知的特性。
以下是您的工作方式:
void use_token()
{
const token& myToken = make_token();
// now myToken is alive until the end of this function.
}
但是你必须严格按值返回才能工作(你在你提供的代码中这样做)。
不相信这一点的人,请在攻击帖子之前亲自尝试。
答案 1 :(得分:8)
像这样:
make_token(),
[](){ /* extra stuff */ }();
确保事后洗手:)
答案 2 :(得分:4)
如果您能够使用C ++ 11或更高版本,则可以编写类似以下内容的模板函数:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp">
<div class="card moveUp" ng-repeat="x in [1,2,3,4,5,6] track by $index" ng-style="{'animation': 'moveUp ' + ($index / 2) + 's ease forwards'}">
<span class="fec">Updated Aug 29, 2016</span>
<span class="title">Internet Banner Advertising…</span>
</div>
</div>
在澄清为什么需要之后编辑:
对于创建令牌以放入{}和缩进的特定用例,您可以创建一个专门命名的包装函数,以明确发生了什么:
template <typename T, typename Functor>
void keep_alive(T&&, Functor f) {
f();
}
...
void use_token() {
keep_alive(make_token(), [&] {
// rest of body of function
});
}
答案 3 :(得分:2)
我们在这里有经典的XY problem:
所以对于C#代码:
using (make_token())
{
// my code here
}
创建一个类令牌:
class token {
public:
token() { // calling make_token(); }
~token() { // destroying token }
};
然后使用它:
{
token tok;
// some stuff here
{
token tok;
// some other stuff here
}
}
所以
如果有必要,你可以把它放到宏中,但是我会发现它更难以使用。
答案 4 :(得分:1)
好吧,你可能认为你可以收到该函数返回的值;
void use_token()
{
auto nonsense = make_token();
// extra code
}
即便如此,你知道吗(Pre-C ++ 17)......当RVO没有发生时,还有两次析构函数调用吗?
以const
引用The Quantum Physicist's answer表示,这是最好的解决方法。
答案 5 :(得分:0)
我感到你的痛苦,auto = make_token()
会很有用。然而...
您可能遇到XY问题。你不应该这样做:
with_token([&]{ ... });
即,令牌生成器/构造函数采用lambda?如果您不想在lambda中编写return
以从创建令牌的实际函数返回,那么这应该。
另一种方法是,如果你只是想让一个人“知道这个名字”,那就是臭名昭着的模式:
template<typename T>
struct Keeper
{
const T t;
char b;
Keeper(const T& t_)
: t(t_) {}
char* begin() { return &b; }
char* end() { return begin() + 1; }
};
template<typename T>
auto make_keeper(const T& t)
{
return Keeper<T>(t);
}
void f()
{
for (char c : make_keeper(make_token()))
{
// now try to name t or Keeper<T>(t) here
}
}
如果愿意,您可以添加移动原理图和完美的转发。