首页 文章

C如何使用类方法正确访问动态数组元素

提问于
浏览
-1

我创建了一个包含动态数组的类Student . 我用构造函数填充了前两个项目 . 我试图用来从主要访问/打印这两个元素的每个方法都会获得读取/访问冲突并崩溃 . 我在构造函数中添加了一个cout,显示元素已填充并存在 . 我在main中包含了两个失败的方法:一个尝试将第一个元素发送到cout的void函数,以及一个接受所需索引的int的方法 . 两者都已被注释掉,以允许测试运行显示元素由构造函数创建和打印 .

Headers :

#ifndef STUDENT_H
#define STUDENT_H
#include <string>
#include <iostream>
#define ARRAY_MAX 15
using namespace std;

class Student
{
private:
    string firstName, lastName;
    unsigned int ID, numItems = 0;
    typedef string* StringPtr;
    StringPtr items;

public:
    int capacity = 15;
    Student();
    Student(const string fName, const string lName, const unsigned int id);
    string getfName() const;
    string getlName() const;
    void getItem(int num);
    string getItemB(int num) const;
    unsigned int getID() const;
};
#endif // STUDENT_H

定义:

#include "student.h"
using namespace std;

Student::Student()
{
}

Student::Student(const string fName, const string lName, const unsigned int id)
{
    firstName = fName;
    lastName = lName;
    ID = id;

    StringPtr items = new string[capacity];
    numItems = 0;
    items[0] = "stuff";
    items[1] = "things";
    cout << items[0] << endl << items[1] << endl;
}

string Student::getfName() const
{
    return firstName;
}

string Student::getlName() const
{
    return lastName;
}

void Student::getItem(int num)
{
    cout << items[0] << endl;
}

string Student::getItemB(int num) const
{
    return items[num];
}

unsigned int Student::getID() const
{
    return ID;
}

主要:

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include "student.h"
using namespace std;



int main()
{
    Student stu;
    string str;

    stu = Student("John", "Smith", 1200);
    cout << stu.getfName() << " " << stu.getlName() << endl;
    //stu.getItem(0);
    //cout << stu.getItemB(0);

    system("pause");

    // Quit without error
    return 0;
}

1 回答

  • 2

    解决方案

    更改

    StringPtr items = new string[capacity];
    

    items = new string[capacity];
    

    TL; DR

    Student::Student(const string fName, const string lName, const unsigned int id)
    {
        firstName = fName;
        lastName = lName;
        ID = id;
    
        StringPtr items = new string[capacity];
        numItems = 0;
        items[0] = "stuff";
        items[1] = "things";
        cout << items[0] << endl << items[1] << endl;
    }
    

    这条线

    StringPtr items = new string[capacity];
    

    创建一个新的自动(本地)变量 items 并初始化它而不是预期的 private 成员变量 StringPtr items; . 这通常称为Variable Shadowing . 本地 items 在函数结束时超出范围,泄漏分配的内存,成员 items 永远不会被初始化,导致 stu.getItem(0); 访问未初始化的指针并触发崩溃 .

    void Student::getItem(int num)
    {
        cout << items[0] << endl; // items points Crom knows where, so items[0] is invalid.
    }
    

    这次崩溃非常幸运 . 访问unitintialized指针会导致Undefined Behaviour,这意味着它可以做任何事情,从看起来像它起作用到导致宇宙爆炸 .

    您必须处理的下一个问题是观察The Rule of Three .

    The best way to deal with this is std::vector

    std::vector<string> items;
    

    std::vector 是符合规则的(Rule of Five,实际上),因此您不必这样做 .

    如果不允许 std::vector ,则需要实现复制构造函数

    Student::Student(const Student & src):
        firstName(src.firstName), lastName(src.lastName),
        ID(src.ID), numItems(src.numItems),
        items(new string[capacity])
    {
        for (int i = 0; i < src.numItems; i++)
        {
            items[i] = src.items[i];
        }
    }
    

    和赋值运算符(为简单起见,利用Copy and Swap Idiom

    Student & Student::operator=(Student src)
    {
        swap(*this,src);
        return *this;
    }
    

    写作 swap 我会留给你 .

相关问题