Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;-在类定义结束时创建的对象的范围_C++_Class_Object_Scope - Fatal编程技术网

C++ C++;-在类定义结束时创建的对象的范围

C++ C++;-在类定义结束时创建的对象的范围,c++,class,object,scope,C++,Class,Object,Scope,如果我有这样的课 class sample{ // ... } obj; 上面创建的对象obj的范围是什么?这个物体什么时候会被销毁 obj的范围与类别定义的范围相同。如果在所有函数之外定义它,它的作用域将是全局的,它将在静态初始化时创建和初始化,并在程序终止时销毁 但是,也可以在函数中定义这样的对象。在这种情况下,它将在函数输入时创建,并在函数返回时销毁 void test() { class sample{ }obj; } 是完全有效的代码 还可以将其定义为类中的嵌套类型。在这

如果我有这样的课

class sample{
  // ...
} obj;

上面创建的对象
obj
的范围是什么?这个物体什么时候会被销毁

obj的范围与类别定义的范围相同。如果在所有函数之外定义它,它的作用域将是全局的,它将在静态初始化时创建和初始化,并在程序终止时销毁

但是,也可以在函数中定义这样的对象。在这种情况下,它将在函数输入时创建,并在函数返回时销毁

void test()
{
   class sample{ }obj;
}
是完全有效的代码

还可以将其定义为类中的嵌套类型。在这种情况下,
obj
将是该类的成员变量。它将随着包含类的对象的构造和销毁而创建和销毁

struct Foo
{
   class sample{ }obj;
};

另外(感谢@sjdalessandro指出这一点),如果对象在库中定义为全局作用域,并且动态加载此库,则在加载库时(不一定在程序启动时)创建该对象,并在卸载库时销毁该对象(程序退出时不一定如此)。

如果类在全局范围内定义,则它将具有全局范围。在这种情况下,对象
obj
将在应用程序启动期间初始化,并在应用程序退出期间销毁。否则,范围将限于类实际定义的位置

观察这种行为很容易。请参见下面的示例类的全局定义

class sample
{
public:
    sample()
    {

    }   
    ~sample()
    {
    }
}Obj;
在构造函数和析构函数中都放置一个断点,并查看调用这两个函数的点。在应用程序启动期间,当调用中的构造函数时,您可以观察调用堆栈,如下所示

App.exe!sample::sample() Line 582   C++
App.exe!`dynamic initializer for 'Obj''() Line 589  C++
msvcr110d.dll!_initterm(void (void) * * pfbegin, void (void) * * pfend) Line 889    C
App.exe!__tmainCRTStartup() Line 460    C
App.exe!wmainCRTStartup() Line 377  C

从上面的调用堆栈中可以看出,类<代码>示例< /C> >被调用为C++启动库初始化的一部分,在应用程序启动期间发生。对类析构函数来说也是如此,即在应用程序退出时调用。


正如@sjdalessandro所指出的,如果对象是在库中定义的,并且该库是动态加载的,那么当库被卸载时,对象就会被销毁;这不一定是在程序退出时。它将具有上述范围声明的范围

例如:

#include <iostream>

namespace A {
    namespace B {
        struct C {
            struct D {
                int e;  // variable e lifetime is same with struct D lifetime. Available only within struct D initialized
                D() : e(42) {}
            } d;    // variable d lifetime is samw with C struct lifetime. Available only within struct C initialized
            C() {}
            C(int v) {
                d.e = v;
            }
        } c;    // variable c lifetime is entire program. Scope is A::B::c
    }
}

int main() {
    // access variable with program lifetime in A::B namespace
    std::cout << A::B::c.d.e << std::endl;

    // create local variable of type A::B::C and access its fields
    A::B::C myc(55);
    std::cout << myc.d.e << std::endl;

    // declare struct F within main function scope and access its fields
    struct F {
        int g;
        F(int v) : g(v) { }
    } f (100);
    std::cout << f.g << std::endl;

    return 0;
}
#包括
名称空间A{
命名空间B{
结构C{
结构D{
int e;//变量e LIFET与结构D LIFET相同。仅在已初始化的结构D中可用
D():e(42){}
}d;//变量d LIFET是具有C结构生命周期的samw。仅在已初始化的结构C中可用
C(){}
C(国际五){
d、 e=v;
}
}c;//变量c生命周期是整个程序。作用域是A::B::c
}
}
int main(){
//A::B命名空间中具有程序生存期的访问变量

std::cout那么对象将在堆中创建吗?它将具有声明它的任何作用域,如果是全局作用域,它将静态创建,如果是方法作用域,它将静态创建。它将永远不会在堆上创建。当它超出作用域时,它将被销毁。@iammilind可能是重复的,但不是这个问题。@EJP,是的,你是对的。在中,它没有讨论
对象。不幸的是,我能找到的另一个对象是和。我正在重新打开Q,看看是否可以关闭它。@iammilind关于全局作用域的任何问题都不会是可接受的重复。问题是什么是作用域,它依赖于上下文。这不一定正确;作用域对象的范围取决于其声明的位置。如果在类中声明了
Obj
,则该对象的范围将由封闭类的实例化确定,如果在函数中声明,则该对象将具有函数范围。您还应删除错误的注释。此外,如果该对象在库中定义,并且该库是动态加载的,然后,当库被卸载时,对象被销毁;这不一定是程序退出时。@EJP我没有理解你。代码中没有注释。正如你所知,另一个是调试器中显示的调用堆栈。我没有说任何关于“在代码中”的内容。在这个问题下,你的错误注释不是一个,而是两个请不要重复您最初在回答中发布的错误信息。除此之外,如果对象在库中定义为全局作用域,并且此库是动态加载的;那么当库卸载时,对象将被销毁;这不一定是程序退出时。@sjdalessandro,非常好。如果您不介意,我将添加这一点答:不客气,请便。