使用"new"的类范围

Class scope using "new"

本文关键字:范围 new 使用      更新时间:2023-10-16

作为一名新的C++爱好者,我仍在努力理解使用"new"创建的类对象的范围。我想我读到,通过使用"new"实例化动态对象,类(和成员)将可以由程序的所有部分直接访问(例如,在其他函数中),因为它不是在堆栈上创建的。

在下面的代码中,我在构造函数中将"tesValue1"的初始值设置为"111",然后尝试在"check_accessibility"函数中将其更新为"222"。编译失败,错误"myGeneralVars"未在此[函数调用]范围内声明。

我们非常感谢任何协助。

//main.cpp
#include <iostream>  
using namespace std;
class generalVars
{
private:    
public:
    //data attributes
    int testValue1; 
    //constructor
    generalVars()
    {
        testValue1= 111;
    }
    ~generalVars(void)
    {
        cout << "destructor code here" << endl;
    };
};
void check_accessibility() {
    myGeneralVars->testValue1= 222;
}
int main(int argc, char *argv[])
{
    generalVars* myGeneralVars = new generalVars; //create on heap
    cout << "Main testvalue1 = " << myGeneralVars->testValue1 << endl; //value set in constructor
    check_accessibility(); //sets testValue to new value
    cout << "Main testvalue1 = " << myGeneralVars->testValue1 << endl; //want "222"
    delete myGeneralVars; //delete from heap
    return 0;
}

它的生存期由您决定。

C++使用了存储持续时间的概念:对象的生存期取决于其实例化的位置和方式。有三(四)种类型的存储持续时间:

  • 静态存储持续时间:对象将在程序开始时初始化,并在程序结束时销毁。全局变量和静态类属性具有静态存储持续时间。

  • 自动存储持续时间:对象的生存期由变量在其中声明的作用域的生存期定义。因此,局部变量的生存期在函数启动时开始,在函数结束时结束。非静态类数据成员也是如此:当对象的生存期开始时,其生存期开始,当对象的生命期结束时结束。

  • 动态存储持续时间:对象是使用newdelete在动态内存上创建的,生存时间由用户决定。当用户执行new时,寿命开始,而当执行delete时,寿命结束。

有关详细信息,请参阅此文档页。

在您的例子中,您实例化了一个具有动态存储持续时间的对象,使用指针变量来保存其内存地址(对象的位置)。由于您从未对该指针执行过delete,因此对象的生存期永远不会结束:这是内存泄漏。

此外,您还尝试访问在另一个函数(check_accessibility)中的一个函数中定义的变量(main)。当然,这个变量在main之外是不可见的。但这与动态存储持续时间无关,只是一个简单的名称查找问题。无论谁告诉您存储持续时间有相关或取决于名称/变量的可访问性,都是完全错误的。

既然你是一个业余爱好者和初学者,让我们早点让你走上正轨,这样你就可以从你的爱好中获得更多的乐趣和享受。

考虑一下我在这里所做的更改,这些更改采用的原则将使您的程序在复杂性增加时变得更加优雅、健壮和令人愉快。

//main.cpp
#include <iostream>  
#include <memory>
using namespace std;
class generalVars
{
private:    
public:
    //data attributes
    int testValue1; 
    //constructor
    generalVars()
    : testValue1(111)
    {
    }
    ~generalVars(void)
    {
        // if the class is carefully written using std:: objects
        // you will rarely need to define a destructor
        cout << "destructor code here" << endl;
    };
};
// pass a reference to a mutable object to ensure that logic 
// is performed on the object and not on its lifetime
void check_accessibility(generalVars& gv) {
    gv.testValue1= 222;
}
int main(int argc, char *argv[])
{
    unique_ptr<generalVars> myGeneralVars(new generalVars); //create on heap *safely*
    cout << "Main testvalue1 = " << myGeneralVars->testValue1 << endl; //value set in constructor
    check_accessibility(*myGeneralVars); //sets testValue to new value
    cout << "Main testvalue1 = " << myGeneralVars->testValue1 << endl; //want "222"
    // no delete necessary - unique_ptr's destructor takes care of it
    return 0;
}

输出:

Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
Executing the program....
$demo 
Main testvalue1 = 111
Main testvalue1 = 222
destructor code here

myGeneralVars不为函数check_accessibility()所知,因此无法访问该变量。相反,尝试将其作为参数传递。

void check_accessibility(generalVars* genVar) {
    genVar->testValue1= 222;
}
int main(int argc, char *argv[])
{
    generalVars* myGeneralVars = new generalVars; //create on heap
    cout << "Main testvalue1 = " << myGeneralVars->testValue1 << endl; //value set in constructor
    check_accessibility(myGeneralVars); //sets testValue to new value
    cout << "Main testvalue1 = " << myGeneralVars->testValue1 << endl; //want "222"
    delete myGeneralVars; //delete from heap
    return 0;
}

myGeneralVar仅在main()作用域内有效,因此check_accessibility()无法访问它。您必须在全局作用域(函数定义外部)中声明它,或者将它作为参数传递给main()内部的check_accessability()。请记住,主函数并不是您可能认为的全局范围。main()和其他函数一样只是一个函数,有自己的作用域。

在函数check_accessibility中,您使用尚未声明的名称myGeneralVars。

void check_accessibility() {
    myGeneralVars->testValue1= 222;
}

所以编译器会发出一个错误。

在使用任何名称之前,必须声明它。

你可以按照的方式编写函数

void check_accessibility( generalVars* myGeneralVars  ) {
    myGeneralVars->testValue1= 222;
}

并称之为

check_accessibility( myGeneralVars ); 

此外,您可以在generalVars类中定义check_accessibility()函数,并将其从main调用为mygeneralVars->check_accessibility();