【问题标题】:Is it possible to explicitly instantiate temporary variables in C++?是否可以在 C++ 中显式实例化临时变量?
【发布时间】:2016-02-18 08:38:15
【问题描述】:

有些人警告说,锁可能会被误用:

std::unique_lock<std::mutex>(mutex);

而不是下面的正确说法:

std::unique_lock<std::mutex> lock(mutex);

即创建一个未命名的临时变量而不是局部变量。临时变量将被立即销毁并提前解锁互斥锁。

例如见gperftools (line 321-324) header:

// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)

编写此宏是为了再次保护此类用例。

但它还能发生吗?显然,在这种情况下,足够近的 GCC 或 clang 会产生错误:

#include <iostream>

class Mutex {};

class Lock {
public:
  explicit Lock(Mutex */* dummy */) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
  ~Lock() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

int main() {
  Mutex mutex;
  {
    Lock l(&mutex);
  }
  {
    Lock(&mutex); // This line does not compile.
  }
  return 0;
}

还有错误:

g++ foo.cpp
foo.cpp:17:11: error: declaration of reference variable 'mutex' requires an initializer
    Lock(&mutex);
          ^~~~~
1 error generated.

有人可以展示一个这样的宏会捕获真正错误的重现案例吗?到目前为止我想不出一个。

【问题讨论】:

标签: c++


【解决方案1】:

实际上,您正在被可声明事物的消歧规则(它们被解析为声明,而不是表达式)以及要求初始化引用的规则所拯救。

这里不会救你的:

std::mutex m;
int main(){
    std::unique_lock<std::mutex>(m); // m is a local default-constructed unique_lock
}

或这里:

struct C { Mutex m; } c;
int main() {
    Lock(&c.m);  // Constructs and destroys a temporary lock.
 }

【讨论】:

  • 对于第一个示例,如果 std::mutex 在 main 内部,如果不编译但如果互斥锁在外部,则非常令人困惑。你能详细说明一下什么样的模式在这里有问题吗?
  • @ThomasMoulard std::unique_lock&lt;std::mutex&gt;(m); 完全等同于 std::unique_lock&lt;std::mutex&gt; m;,因为它被解析为声明。现在应该很明显了,如果互斥锁在 main 内,为什么它不会编译。
猜你喜欢
  • 2016-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多