局部变量的作用域问题(Local variable scope question)

2019-07-05 08:25发布

为什么下面的代码打印“XXY”? 应该不是局部变量住在整体功能的范围是什么? 我可以用这样的行为或这将在未来的C ++标准是否会改变?

我认为,根据C ++标准3.3.2“ 在一个块中声明的名称是局部的块,其电势范围起始于它的点声明的,并且在其声明区域的结尾处结束。”

#include <iostream>
using namespace std;

class MyClass
{
public:
  MyClass( int ) { cout << "x" << endl; };
  ~MyClass() { cout << "x" << endl; };
};

int main(int argc,char* argv[])
{
  MyClass  (12345);
// changing it to the following will change the behavior
//MyClass m(12345);
  cout << "Y" << endl;

  return 0;
}

基于响应我可以假设MyClass(12345); 是表达式(和范围)。 这是有意义的。 因此,我希望下面的代码将打印“XY-X”总是:

MyClass (12345), cout << "Y" << endl;

并且允许做出这样的替换:

// this much strings with explicit scope
{
  boost::scoped_lock lock(my_mutex);
  int x = some_func(); // should be protected in multi-threaded program
} 
// mutex released here

//    

// I can replace with the following one string:
int x = boost::scoped_lock (my_mutex), some_func(); // still multi-thread safe
// mutex released here

Answer 1:

你引用标准正确。 我要强调:

在一个块中声明名字是局部的该块。 其潜在的范围起始于它的点声明的,并且在其声明区域的结尾处结束。

你没有申报任何名义 ,实际上。 你

MyClass (12345);

甚至不含有宣言 ! 它所包含的内容是创建MyClass的实例,计算表达式(但是,在这种特殊情况下没有什么计算),并且降其结果的表达式void ,并破坏那里创建的对象。

一个不太令人困惑的事情的声音听起来象

call_a_function(MyClass(12345));

你看到了很多次,知道它是如何工作的,不是吗?



Answer 2:

在创建的对象的

MyClass(12345);

是临时对象是仅在该表达活着;

MyClass m(12345);

是一个对象,它是活着的整个块。



Answer 3:

你没有保持它的范围实际上是创建一个对象,所以它被摧毁它被创建之后。 因此,您所遇到的行为。

您无法访问所创建的对象那么,为什么编译器保持它周围?



Answer 4:

为了回答您的其他问题。 以下是逗号操作的调用。 它创建一个MyClass临时工,其中包括调用其构造函数。 然后,计算第二个表达式cout << "Y" << endl将打印出Y.然后它,在充分表达结束后,会破坏临时,它会调用析构函数。 所以,你的预期是正确的。

MyClass (12345), cout << "Y" << endl;

对于下面的工作,你应该加括号,因为逗号在声明一个预定义的含义。 它将开始声明一个函数some_func返回一个int和采取任何参数,将在指定scoped_lock对象x 。 使用括号,你说,整个事情是一个逗号操作符表达式来代替。

int x = (boost::scoped_lock (my_mutex), some_func()); // still multi-thread safe

应当指出的是,下面的两行是等价的。 先创建使用临时无名对象my_mutex作为构造函数的参数,而是围绕着名的括号是多余的。 不要让语法迷惑你。

boost::scoped_lock(my_mutex);
boost::scoped_lock my_mutex;

我见过的条款范围和寿命的滥用。

  • Scope是在那里你可以参考的名称,而不必限定其名称。 名称有范围和对象继承用来定义它们的名称的范围(因此有时标准说“本地对象”)。 临时对象没有范围,因为它有没有名字。 同样,通过创建一个对象new没有范围。 适用范围是一个编译时间属性。 这个术语是在标准经常被滥用,看到这个缺陷报告 ,所以它是相当混乱找到了真正的意义。

  • Lifetime是运行时属性。 当对象被设置和准备使用它的意思。 对于一类类型的对象中,当构造结束执行的寿命开始时,并且当析构函数开始执行结束。 寿命往往混淆范围,虽然这两样东西是完全不同的。

    临时对象的寿命精确限定。 他们中的大多数它们包含在(例如,上述逗号运算符,或者赋值表达式)充分表达的评价之后结束寿命。 临时对象可以绑定到const的,这将延长其寿命的引用。 在异常被抛出的对象是临时变量太多,而当没有处理他们了他们的一生结束。



文章来源: Local variable scope question
标签: c++ scope raii