C++11自动声明外部作用域变量

3

在C++中,如果支持,使用auto来声明许多变量是一种良好的实践,特别是对于那些类型已知但难以输入的变量:

weird_template_type<int,char>::subtype::recursive_subtype some_function() {
    // ...
}
// ...
auto val = some_function();

当需要对锁进行操作时,使用RAII对象的微型作用域也是一个不错的选择:

some_setup_code();
int val;
{
    lock_guard<mutex> lk(mut);
    val = read_shared_memory();
}
do_something(val);

你有办法将这两个习语混合使用吗?例如,当您的共享内存读取代码返回奇怪的类型时?

显而易见的版本不起作用:

auto val;
{
    lock_guard<mutex> lk(mut);
    val = read_shared_memory();
}
do_something(val);

由于一个没有初始化程序的auto变量,编译时会出现错误。

同样地,您不能在作用域块内声明变量,否则它就无法在稍后使用。

我能想到的唯一的即时选项是1.显式地输入变量声明(不好),或者2.使用您知道的与相同类型的其他表达式一起使用auto(不是改进)。还有其他方法吗?


也许是 decltype() - HolyBlackCat
1
auto val = (lock_guard<mutex>(mut), read_shared_memory()); do_something(val); - cpplearner
我想指出,在大多数情况下,为了锁定目的在“真实”范围中间打开一个新范围,这表明存在设计问题。你应该考虑为什么要这样做。 - ZivS
@ZivS 为什么这样说呢?这只是从1.保持关键部分小和2.使用RAII的自然结论。那么,什么是首选设计呢? - Tom Hunt
这取决于使用情况。但是在您的代码中,为什么锁不在read_shared_memory函数内部? - ZivS
在我的情况下,共享内存是将项目传递给工作线程的队列,而read_shared_memory()只是queue_.size()。在这里添加一个仅有两行且仅被调用一次的单独函数似乎并不值得。 - Tom Hunt
3个回答

15

基本上,您所说的是复杂变量初始化。典型的解决方案是使用lambda:

auto val = [&]() {
    lock_guard<mutex> lk(mut);
    return read_shared_memory();
}();

这是我过去考虑过的事情,但我认为这可能会让未来的维护者感到困惑。你怎么知道这是“典型”的解决方案? - Kyle Strand
JS开发人员会称其为IIFE;从那个上下文中,我立即就能熟悉它。不确定有多少重叠,但我这边没有任何困惑。 - Tom Hunt
3
你仍然可以使用常规函数,这是更为传统的做法,但对于可重用性更好。 - Jarod42
@Jarod42 是的,那是我通常倾向的方法。虽然我喜欢lambda方法避免了大量调用非线程安全的“do_some_thing()”函数的safe_do_some_thing()函数的出现。 - Kyle Strand

8
您可能会考虑
decltype(read_shared_memory()) val;
{
    lock_guard<mutex> lk(mut);
    val = read_shared_memory();
}
do_something(val);

虽然它不一定更简洁。

违反DRY原则,存在更好的解决方案...请勿使用。 :) - GManNickG
抛开DRY原则的违反,这个解决方案要求你初始化的类型可以被默认构造。 - Nicol Bolas
@GManNickG 噢,我同意,它不是最简洁的。但是想象一下如果我们有多个变量需要设置,那么lambda表达式看起来也不好看。(顺便说一句,我个人喜欢**@cpplearner**放置注释的那个版本。: )) - AlexD

3
您可以创建一个辅助函数来实现这个功能:
int read_shared_int_memory(std::mutex &mut);
{
    std::lock_guard<std::mutex> lock(mut);
    return read_shared_memory();
}

然后,简单地:
auto val = read_shared_int_memory(mut);

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