使用"new"的类范围
Class scope using "new"
作为一名新的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++使用了存储持续时间的概念:对象的生存期取决于其实例化的位置和方式。有三(四)种类型的存储持续时间:
-
静态存储持续时间:对象将在程序开始时初始化,并在程序结束时销毁。全局变量和静态类属性具有静态存储持续时间。
-
自动存储持续时间:对象的生存期由变量在其中声明的作用域的生存期定义。因此,局部变量的生存期在函数启动时开始,在函数结束时结束。非静态类数据成员也是如此:当对象的生存期开始时,其生存期开始,当对象的生命期结束时结束。
-
动态存储持续时间:对象是使用
new
和delete
在动态内存上创建的,生存时间由用户决定。当用户执行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();
- 为什么在全局范围内使用"extern int a"似乎不行?
- 尝试通过多个向量访问变量时,向量下标超出范围
- 错误:未在此范围内声明'reverse'
- 正在将指针转换为范围
- 使用std::transform将一个范围的元素添加到另一个范围中
- 在基于范围的for循环中使用结构化绑定声明
- 如何计算数据类型的范围,例如int
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 如果"new int"返回"int*",那么为什么"new int[n]"不返回"int**"?
- 在C++中查找范围的长度
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- 重载运算符new[]的行为取决于析构函数
- 如何设置一个范围来提取我想要获得的信息
- 并行用于C++17中数组索引范围内的循环
- 为左值和右值的包装器实现C++范围
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 为什么当我尝试对使用 New 函数启动的对象调用删除函数时出现范围错误?
- C++本地对象超出范围,返回指针(使用new分配的内存).因此内存泄漏
- 当退出 new/malloc 函数时,从 new/malloc 返回的指针如何保持在范围内
- 使用"new"的类范围