1

我无法弄清楚我做错了什么?我有一堂课,里面有私人数据:

static const int SIZE = 101;
int *ptr;
int set [SIZE];

我有 2 个构造函数。一个是将数组设置为 0 的默认构造函数。另一个接受 5 个参数并将数组中的 5 个值设置为 1。我需要打印这个数组。当我在构造函数中时,一切正常,当我在构造函数中执行 cout << 时,结果是正确的。但是当我尝试使用功能打印时。结果是垃圾。我做错了什么?

IntegerSet::IntegerSet() //default constructor
{
    int set[SIZE] = {0};
    ptr = set;
    cout << "Default Constructor: " << endl;
    for (int i =0; i<SIZE ;i++)
    {
        cout << set[i] << " ";
    }
    cout << endl;
}


IntegerSet::IntegerSet(int a, int b, int c, int d, int e)
{
    int set[SIZE] = {0};
    ptr = set;

    ptr[a] = ptr[b] = ptr[c] = ptr[d] = ptr[e] = 1;

    cout << "Constructor with 5 parametrs: " << endl;
    for (int i =0; i<SIZE ;i++)
    {
        cout << ptr[i] << " ";
    }
    cout << endl;
}

void IntegerSet::print() const
{
    bool flag = false;
    cout << "I am in print: " << endl;

    for (int i=0;i<SIZE;i++)
    {
        if (ptr[i]==1)
        {
            cout << i << " ";
            flag = true;
        }
    }
    if (flag == false)
        cout << "-----";
    cout << endl;
}


void main()
{
    IntegerSet s1;
    IntegerSet s2(1,50,10,22,98);

    s2.print();
}
4

6 回答 6

6

您的每个构造函数都声明了一个新数组,该数组名为set该类成员的影子。

于 2013-10-23T19:24:54.680 回答
1

您将 ptr 设置为在构造函数中定义的集合,而不是作为类变量的集合。在构造函数中更改以下内容:

int set[SIZE] = {0};
ptr = set;

set[SIZE-1] = {0};
ptr = set;
于 2013-10-23T19:26:01.353 回答
1

除了我的其他答案之外,这是我关于代码质量和可维护性的建议。您应该使用容器,例如std::array编译时数组,以及用于初始化数据成员的成员初始化器列表。

您误解了以下代码行将内容设置set为0。

int set[SIZE] = {0};

相反,它掩盖了类中的私有数据成员setIntegerSet在构造函数中创建了一个局部变量。这就是您应该使用 STL 容器来完成这些壮举的原因之一。例如:

#include <array> // for std::array

class IntegerSet
{
private:
    std::array<int, 101> set;
public:
    IntegerSet()
        : set() // zero-initializes each element
    {
        for (auto val : set)
            std::cout << val " ";
        std::cout << std::endl;
    }

    IntegerSet(int a, int b, int c, int d, int e)
        : set()
    {
        set[a] = set[b] = set[c] = set[d] = set[e] = 1;

        for (auto val : set)
            std::cout << val " ";
        std::cout << std::endl;
    }
};
于 2013-10-23T20:08:16.030 回答
0

int set[SIZE] = {0};还放入了构造函数,它在堆栈上定义了一个局部set变量(这“遮蔽”了也称为 的私有成员变量set)。

如果您尝试这样做set[SIZE] = 0(将 set 的最后一个元素设置为 0),那么您会遇到第二个错误:您正在访问set越界(C 和 C++ 中的数组是 0 索引的。所以大小为 5 的数组有效索引(0、1、2、3 和 4))。你应该这样做set[SIZE-1] = 0。或者更好的是,使用std::vectoror std::array(C++11) 代替 C 风格的数组。

于 2013-10-23T19:26:51.997 回答
0

数组set对于构造函数是本地的。因此,指向 ,latter 的指针指向ptrNULL set,因为set当控件离开构造函数时数组不存在。

使用作为set实例变量的数组,以便set在构造函数和print方法中都有相同的实例。

IntegerSet::IntegerSet()                                            //default constructor
{
    set[SIZE-1] = {0};
    ptr = set;
    cout << "Default Constructor: " << endl;
    for (int i =0; i<SIZE ;i++)
    {
        cout << set[i] << " ";
    }
    cout << endl;
}


IntegerSet::IntegerSet(int a, int b, int c, int d, int e)
{
    set[SIZE-1] = {0};
    ptr = set;

    ptr[a] = ptr[b] = ptr[c] = ptr[d] = ptr[e] = 1;

    cout << "Constructor with 5 parametrs: " << endl;
    for (int i =0; i<SIZE ;i++)
    {
        cout << ptr[i] << " ";
    }
    cout << endl;
}
于 2013-10-23T19:32:48.920 回答
0

这是您的垃圾输出的解释:

ptr[a] = ptr[b] = ptr[c] = ptr[d] = ptr[e] = 1;
// ...
for (int i = 0; i < SIZE; i++)
{
    cout << ptr[i] << " ";
}

在您的 main 方法中,您使用了参数 1、50、10、22 和 98。因此,上述示例中的第一行等价于:

ptr[1] = ptr[50] = ptr[10] = ptr[22] = ptr[98] = 1;

这并没有错。问题是它下面会发生什么。在您的for()循环中,您尝试ptr从其第一个索引 ( 0) 迭代到SIZE. 您只给出了数组中 5 个位置的值,因此其他位置未初始化。这会导致您的程序出现未定义的行为,并且是垃圾输出的原因。

您应该单独使用索引打印值。

但是,除非您能告诉我们您这样做的原因是什么,否则我无法提出更好的替代方法。

于 2013-10-23T19:37:08.983 回答