超出范围意味着什么在c ++对象中意味着什么?

时间:2016-01-04 07:00:29

标签: c++

我知道一个对象超出范围的情况。例如,假设我们从main()调用了函数foo()。

int foo()
{
   someobject obj;

   //do something with this object

   return -1;
}

现在我知道,因为这个对象是在堆栈上声明的,所以当foo()结束时,这个对象将从堆栈中删除。 有人可以解释 其他对象超出范围的情况吗? 另一件事, 为什么这个对象在堆栈上声明?

3 个答案:

答案 0 :(得分:1)

void foo()
{
    int obj1;
    {
        int obj2;
        // obj1, obj2 can be used here
        {
            int obj1;
            //in this scope obj1 is not the first obj1, it's the one declared in previous line
        }
        // obj1 in this will refer the first obj1
    }
}

关于在函数内创建一些对象时默认的第二个问题,它将在堆栈上。它是首选的,因为我们不必处理分配的内存。它将自动从堆栈中删除。

我们可以使用new在堆上创建内存但是在这种情况下我们必须确保一旦完成,我们已经删除了已分配的内存,或者确保转移了对象的所有权以便删除它。

检查以下情况。

void foo1()
{
    int* i = new int(23);
    // use i here ...
    // .....
    delete i; // once done delete the memory, it exception is thrown here i will not be deleted so make sure to use smart pointer(RAII)
}

void foo2()
{
    unique_ptr<int> iPtr(new int(23));
    // use iPTr here ...
    // .....
    // no need to delete allocated memory, unique_ptr will handle that
}

为避免不必要的内存管理,我们在堆栈上创建对象。同样在嵌入式域中,不建议使用动态内存分配,因为它不安全。

答案 1 :(得分:0)

这是在栈上声明的对象,因为一旦调用了这个返回的整数函数,就可以说它已经实现了它的目的。我会说你首先使用这个对象的方式有点奇怪。为什么不直接将对象的引用作为函数的输入参数传递。

int foo(object) {


}

对于其他对象可能超出范围的情况,仅取决于创建对象的线程或位置。

答案 2 :(得分:0)

C ++中有两个重要概念:

  • 范围
  • 存储时间

这两者相互作用但是截然不同。 (还有第三个概念,对象生命周期,,对于“普通”程序几乎与对象的存储持续时间相同;让我们暂时忽略它。)

我们来看看范围

范围表示“名称在哪里可见且有效”。中心概念是名称。标准在3.3.1中说明

  

通常,每个特定的名称仅在某些可能的范围内有效   程序文本的不连续部分称为范围。 [由我强调。]

i之类的名称可能超出范围。这意味着不能再使用它来引用特定对象。您给出的示例是正确的:当一个封闭的块(如函数体)被留下时。另一个例子是两个实体具有相同的名称,如全局i和本地循环变量i。全局i范围不包含循环(这是一个不同的i)。但是全局i对象的存储持续时间(以及生命周期)当然包括循环 - 它仍然是“那里”(例如,可以使用指针访问它)。

相比之下,存储持续时间不是正式的语法问题,而是实际的运行时间问题。中心概念是存储:适当命名的存储持续时间描述了持有对象的存储有效的时间。 (请参阅此处我们如何关注名称。)标准在3.7中说明:

  

存储持续时间是定义的对象的属性   包含存储的最小潜在生命周期   物体。存储持续时间由   用于创建对象的构造,并且是以下之一:

     
      
  • 静态存储时间
  •   
  • 线程存储持续时间
  •   
  • 自动存储时间
  •   
  • 动态存储时间
  •   
     

[我强调。]

最简单的“创建对象的构造”是简单地在函数内声明局部变量。这样创建的存储具有恰当命名的“自动”存储持续时间 - 实现在执行定义时创建对象(最新?),并在保留名称范围时为您销毁对象。对于自动变量,名称范围和存储持续时间之间的连接很强。

但请注意,也可以在块内声明外部变量或函数,因此具有外部实体的本地范围名称:

$ cat local-external.cpp && g++  -Wall -o local-external local-external.cpp && ./local-external
int main()
{
        {
                extern int i;
        }
        i=1;
}
local-external.cpp: In function ‘int main()’:
local-external.cpp:4:14: warning: unused variable ‘i’ [-Wunused-variable]
   extern int i;
              ^
local-external.cpp:6:2: error: ‘i’ was not declared in this scope
  i=1;
  ^

i范围与局部变量相同 - 从声明到封闭块的末尾 - 但是它的存储持续时间(如果存在对象)例如,在不同的文件中定义)将是静态的,因为它是一个外部变量,并且与程序一样长。如果将赋值移动到内部块以便代码编译,则链接器会抱怨它无法找到外部对象i(应该在某处留出的存储空间)。

当然很少有这样的事情;这只是一次示威。 (声明本地函数可能最常做inadvertently。)