visual studio中c++指针的问题(但在g++中工作)

problem with c++ pointers in visual studio (but works in g++)

本文关键字:但在 g++ 工作 studio c++ 指针 visual 问题      更新时间:2023-10-16

当我在Microsoft visual studio中运行以下代码时,它会输出垃圾值(内存地址?),但当它在g++中运行时,它会输出我想要的内容(通过一些更改,如更改srand)。我如何修复它在visual studio工作?我只有几个月的编码经验,这个问题已经困扰我一段时间了。

class Vehicle
{
    protected:
        int * vin;
        double * gasMileage;
    public:
        Vehicle();
        Vehicle(int v, double g);
        virtual void display(){cout<<"vin: "<<*vin<<endl<<"gasMileage: " <<*gasMileage<<endl;}
        virtual double calcGasUsed(int milesDriven){return *gasMileage * milesDriven;}
        int getVin(){return *vin;}
        double getGasMileage(){return *gasMileage;}
        void changeVin(int newvin) {vin=&newvin;}
        void changeGasMileage(double newGasMileage){gasMileage=&newGasMileage;}
        void drive();
};
class Suv:public Vehicle
{
    protected:
        bool *fourWDStatus;
        double * fourWDGasMileage;
    public:
        Suv();
        Suv(int v, double g,bool status, double fwdg);
        void display();
        double calcGasUsed(Suv&, int milesDriven);
        bool getFourWDStatus(){return *fourWDStatus;}
        double getfourWDGasMileage(){return *fourWDGasMileage;}
        void changeFourWDStatus(bool status) {fourWDStatus=&status;}
        void changeFourWDGasMileage(double newGasMileage){fourWDGasMileage=&newGasMileage;}
};
Vehicle::Vehicle()
{
    this->vin=0000;
    this->gasMileage=00;
}
Vehicle::Vehicle(int v, double g)
{
    this->vin=&v;
    this->gasMileage=&g;
}
Suv::Suv(int v, double g,bool status, double fwdg)
{
    this->vin=&v;
    this->gasMileage=&g;
    this->fourWDStatus=&status;
    this->fourWDGasMileage=&fwdg;
}
Suv::Suv()
{
    this->vin=0000;
    this->gasMileage=00;
    this->fourWDStatus=false;
    this->fourWDGasMileage=00;
}
void Suv::display()
{
    Vehicle::display();
    cout<<"fourWDStatus: "<<*fourWDStatus<<endl<<"fourWDGasMileage: "<<*fourWDGasMileage<<endl;
}
void Vehicle::drive()
{
    int r=rand()%10000;
    cout<<calcGasUsed(r)<<endl;
}
double Suv::calcGasUsed(Suv&, int milesDriven)
{
    double x;
    if (*fourWDStatus== true)
    {
        x= ((*fourWDGasMileage) * (milesDriven));
        return x;
    }
    else
    {
        x=((*gasMileage) * (milesDriven));
        return x;
    }
}
void main()
{
    cout << "test";
    srand(NULL);
    Suv A(300,12.2,false,16.6);
    Suv B(200,15.5,false,20.1);
    B.changeFourWDStatus(true);
    Vehicle C(111,20.5);
    C.drive();
    C.display();
    B.display();
    Vehicle arrOfCars[]={A,B,C};
    A.drive();
    B.drive();
    C.drive();
    system("pause");
}

您在使用指针时没有将其初始化为任何东西。我很快就发现,成员变量都不应该是指针,构造函数参数都不应该是引用。在其他地方,将int赋值给int*。编译器给你警告了吗?

两个更奇怪的事情:为什么用四位数字的0000作为整数字面值,为什么用system("pause") ?

不要将类的数据成员存储为指针。没有必要给出你的用法。乍一看,我发现这里有一个问题:

void changeGasMileage(double newGasMileage){gasMileage=&newGasMileage;}

这样做的是将gasMileage设置为指向堆栈上分配的值。当changeGasMileage返回时,您不再知道该内存位置上的内容。您可以将gasMileage设置为一个值而不是一个指针。否则,您需要执行:

void changeGasMileage(double newGasMileage){gasMileage= new double(newGasMileage);}

成员Vehicle::vinVehicle::gasMileageSuv::fourWDStatusSuv::fourWDGasMileage是未正确初始化的指针。

从你发布的代码看来,你会更好地将它们从指针改为常规变量(并适当地调整方法)。

编辑:如果使用指针是赋值操作的一部分,则必须正确初始化它们。这意味着,在您的情况下,在构造函数中分配内存。可以是这样的:

Vehicle::Vehicle()
{
    this->vin = new int(0);
    this->gasMileage = new double(0.0);
}
Vehicle::Vehicle(int v, double g)
{
    this->vin = new int(v);
    this->gasMileage = new double(g);
}
Suv::Suv(int v, double g,bool status, double fwdg) : Vehicle(v, g)
{        
    this->fourWDStatus = new bool(status);
    this->fourWDGasMileage = new double(fwdg);
}
Suv::Suv() : Vehicle(0, 0.0)
{
    this->fourWDStatus = new bool(false);
    this->fourWDGasMileage = new double(0.0);
}

其他人已经讨论了不适合此场景的指针的使用。我同意。

同样,当构造函数接收到按值复制时,要获取其地址的值驻留在(调用)堆栈上。当该构造函数退出时,局部变量被解构(对于内置类型,int, char, float等通常是无操作的),并且通过指针访问它们是"未定义行为"。

为什么会这样: 未定义的行为意味着允许任何事情发生。最好是编译器诊断,或者是崩溃,或者更糟糕的是,可以看到损坏的数据,但最坏的情况是,巧合使它工作到稍后一段时间-参见巧合编程。

一旦构造函数退出,这个区域将被打开,以便在调用其他函数时重用——它们将需要一个地方来存储它们的局部变量、参数和调用其他函数的参数/返回地址。

巧合的是,gcc(那个版本,那些编译器标志)并没有覆盖堆栈上用于打印值的位置,因此您读取的值就是您期望的值。

相关文章: