C ++中的静态变量和对象寿命

时间:2015-02-11 23:02:42

标签: 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,以便代码尽可能短,只有相关信息。

2 个答案:

答案 0 :(得分:2)

我认为你的主要问题是你已经定义了一个空的复制构造函数:

Vehicle::Vehicle(const Vehicle& orig)
{
}

这意味着当您向容器添加Vehicle时,会制作一个实际上并未复制任何内容的副本。您应该删除自己的构造函数,让编译器为您完成工作。

答案 1 :(得分:0)

如果不使用指针或引用,则永远不会遇到对象生命周期的问题。它不可能发生。 “RAII”的整个概念是,如果变量可以在代码中访问,那么它就是有效的。

要测试此功能,还要打印出车辆的坐标和尺寸。如果打印出有效的结果,您就知道问题出在paint函数本身。

所以除非你需要修改它,否则不要传递对象的指针,甚至然后返回引用而不是指针。请确保不要返回临时引用,因为这会导致生命周期问题。