C++中的静态变量和对象寿命
Static variable and object life span in C++
我是C++的初学者,我理解"通过值或引用传递"、对象范围和对象实例化的基本概念,在简单示例中使用和不使用关键字"new"。问题是,当我试图解决的问题变得更加复杂时,我不知道我从简单的例子中了解到的这个理论是如何应用于由多个类组成的问题的。
我有一个PaintWidget.cpp,负责为所有车辆喷漆。
void PaintWidget::paintEvent(QPaintEvent *) {
if (!Vehicle::GetVehicles()->empty()) {
cout << "not null" << endl;
QPainter painter(this);
QPen pen1(Qt::red);
pen1.setWidth(2);
std::vector<Vehicle>::iterator it;
for (it = Vehicle::GetVehicles()->begin(); it != Vehicle::GetVehicles()->end(); it++) {
cout << "draaaaw" << endl;
QRect rect(it->GetXcord(), it->GetYcord(), it->GetWidth(), it->GetHeight());
cout << std::to_string(it->GetXcord()) + " " + std::to_string(it->GetYcord()) + " " + std::to_string(it->GetWidth()) + " " + std::to_string(it->GetHeight()) + " " << endl;
painter.setPen(pen1);
painter.drawRect(rect);
}
} else {
cout << "is null" << endl;
}
}
然后我有Vehicle.h
#ifndef VEHICLE_H
#define VEHICLE_H
#include <vector>
#include <map>
class Vehicle {
public:
Vehicle();
Vehicle(const Vehicle& orig);
virtual ~Vehicle();
void initVehicles();
Vehicle createVehicle();
static std::map<Road, int> &GetVeh_num() {
return veh_num;
}
static std::vector<Vehicle> *GetVehicles() {
return &vehicles;
}
private:
int xcord;
int ycord;
int height = 20;
int width = 50;
static std::vector<Vehicle> vehicles;
static std::map<Road, int> veh_num;
};
#endif /* VEHICLE_H */
Vehicle.cpp
#include "Vehicle.h"
#include <vector>
std::vector<Vehicle> Vehicle::vehicles;
std::map<Vehicle::Road, int> Vehicle::veh_num = {
{Vehicle::Top, 0},
{Vehicle::Right, 0},
{Vehicle::Bottom, 0},
{Vehicle::Left, 0}
};
Vehicle::Vehicle() {
}
Vehicle::Vehicle(const Vehicle& orig) {
}
Vehicle::~Vehicle() {
}
int Vehicle::GetXcord() const {
return xcord;
}
int Vehicle::GetYcord() const {
return ycord;
}
void Vehicle::SetXcord(int xcord) {
this->xcord = xcord;
}
void Vehicle::SetYcord(int ycord) {
this->ycord = ycord;
}
int Vehicle::GetHeight() const {
return height;
}
int Vehicle::GetWidth() const {
return width;
}
void Vehicle::initVehicles() {
for (int i = 0; i < 5; i++) {
Vehicle::vehicles.push_back(this->createVehicle());
}
}
Vehicle Vehicle::createVehicle() {
std::map<Vehicle::Road, int>::iterator it;
Vehicle v;
for (it = Vehicle::veh_num.begin(); it != Vehicle::veh_num.end(); it++) {
int &vehnum = it->second;
if (it->first == Vehicle::Road::Right) {
int xc = 520 + vehnum * this->GetWidth() + vehnum * 5;
int yc = 220;
v.SetXcord(xc);
v.SetYcord(yc);
v.SetRoad(Vehicle::Right);
}
}
return v;
}
如您所见,createVehicle返回一个新Vehicle的副本,然后将其插入静态变量Vehicles中。GetVehicles返回插入车辆的矢量指针,因为我不想返回副本。当我运行此代码时,尽管静态变量中有5个对象,但没有绘制任何对象(paintEvent被调用,字符串"draaaaw"被打印5次)。我怀疑我的物体寿命有问题,所以我换了
static std::vector<Vehicle> vehicles;
至
static std::vector<Vehicle*> vehicles;
当然还有来自的车辆实例化
Vehicle v;
至
Vehicle *v = new Vehicle();
如果我理解正确的话,它会在堆上创建一个对象。在对方法进行了所有必要的更改之后,我的代码就可以工作了(所有对象都已绘制)。我不明白的是,如果我每次都返回一份副本,这些对象什么时候被销毁,为什么会被销毁。为什么矢量车辆不是空的(我仍然有5个"重影"对象,它们不包含我之前设置的任何值)。据我所知,不建议使用new创建对象,所以第二个选项是智能指针?
谢谢:)
编辑我特意在.h和.cpp文件中省略了setter和getter,以便代码尽可能短,只包含相关信息。
我认为您的主要问题是定义了一个空的复制构造函数:
Vehicle::Vehicle(const Vehicle& orig)
{
}
这意味着,当您将Vehicle
添加到容器时,会生成一个实际上并不复制任何内容的副本。你应该删除你自己的构造函数,让编译器为你做这项工作。
如果不使用指针或引用,对象的寿命将永远不会有问题。这根本不可能发生。"RAII"的整个概念是,如果变量在代码中是可访问的,那么它就是有效的。
为了测试这一点,还可以打印出车辆的坐标和尺寸。如果打印出有效的结果,那么您就知道问题出在绘制函数本身。
所以,除非需要修改对象,否则不要传递对象的指针,即使这样,也要返回引用而不是指针。只是要确保不要返回临时的引用,因为这可能会导致寿命问题。
- 你能重载对象变量名本身返回的内容吗
- 为什么我可以使用 memcpy 将一个对象变量复制到另一个对象变量
- 如何使用std::lower_bound比较对象变量,而不使用第二个对象进行比较
- 将私有对象变量与用户输入的变量进行比较
- 具有已定义操作重载的 C++ 非类型化值对象/变量库
- 如何对对象数组进行排序,而不考虑对象变量类型
- 在功能中设置对象变量
- 如何创建对象变量,以便每次分配新的指针
- C++ FileIO 以读取和写入对象变量
- 私下声明的对象变量的突变器/访问器方法
- C++ 列表中的对象变量在迭代过程中不会更新
- 稍后使用私有对象变量时如何初始化数组(初始化对象后)
- 通过向量更改对象变量的值
- C 全局对象变量内存释放
- 基本数据类型变量 VS 对象变量
- C 复制分配运算符,用于参考对象变量
- c++从列表中移除元素,并将其分配给对象变量
- 我们是否需要在C++中同步局部对象变量
- 点运算符和箭头运算符之间的区别 结构对象变量 在 C 或 C++ 中创建树
- 无法访问在 std 回调中传递的对象变量