【问题标题】:C++: function to expand an arrayC++:扩展数组的函数
【发布时间】:2014-02-15 23:54:30
【问题描述】:

在问这个问题之前,我查看了this similar question 并尝试使用它的代码来解决我的问题,但是它没有工作。

我正在尝试编写一个扩展给定静态对象数组的函数。这是目前的功能,基于上述链接问题的代码:

void MyClass::expand_array(MyClass *&old_array, int &old_array_size,
    int new_slots)
{
    MyClass *transfer_array = new MyClass[old_array_size + new_slots];

    for (int i = 0; i < old_array_size; i++) {
        transfer_array[i] = old_array[i];
    }

    delete[] old_array;
    old_array = transfer_array;
    transfer_array = NULL;
}

这甚至不能编译。这是编译器的输出:

program.cpp:110:54: error: no matching function for call to ‘MyClass::expand_array(MyClass [10], int&, int)’
program.cpp:110:54: note: candidate is:
program.cpp:41:6: note: static void MyClass::expand_array(MyClass*&, int&, int)
program.cpp:41:6: note:   no known conversion for argument 1 from ‘MyClass [10]’ to ‘MyClass*&’
program.cpp:122:54: error: no matching function for call to ‘MyClass::expand_array(MyClass [10], int&, int)’
program.cpp:122:54: note: candidate is:
program.cpp:41:6: note: static void MyClass::expand_array(MyClass*&, int&, int)
program.cpp:41:6: note:   no known conversion for argument 1 from ‘MyClass [10]’ to ‘MyClass*&’
program.cpp:143:11: warning: deleting array ‘MyClass tmp_cards [10]’ [enabled by default]

(输出的最后一行来自尝试删除数组的最后一次迭代。)

【问题讨论】:

  • 该错误与您调用该函数的方式有关。第一个参数引用一个指针,但您提供的是一个数组。
  • 不相关,但考虑返回新数组。这是(更好的)自我记录。 (如果是我的代码,我根本不会修改 old_array 指针。但是,每个人都有自己的。)
  • @0x499602D2 那么,将数组传递给函数的正确方法是什么?
  • @jpaugh 原始数组需要通过其中几个操作来保持相同的名称,我认为返回是不可能的。另外,我不知道你可以在 C++ 中返回一个数组。
  • 你不能返回指向任何东西的指针吗?但我离题了.. C++ 不是我的强项;祝你好运。

标签: c++ arrays memory-management


【解决方案1】:

您似乎违反了数组指针等效性。 array 在这种情况下,我指的是 C 数组,例如

MyClass a[10];

在 C 和 C++ 中,数组可以衰减为指针。

void f(int input[]);

语言没有为这个函数提供机制来告诉它接收了多少,所以为了函数调用的目的,上面的数组衰减为一个指针。也就是说,在上述函数体内,input 的类型为 int*。

这也发生在其他地方,允许我们在没有数组的情况下进行指针数学运算和对数组进行类似指针的操作:

char a[10];
sizeof(a); // understands a is really an array and evaluates to 10
sizeof(*a); // decays a to a pointer and returns sizeof(char)
char* b = a + 1; // equivalent to b = &a[1];
b[1] = 0; // equivalent to *(b + 1) = 0;

但是,您正在尝试获取对指针的引用。在这种情况下,数组不会衰减,请考虑:

void f(int*& ptr)
{
    ptr = nullptr;
}

void x()
{
    int a[16];
    f(a);
}

a 不是指向 16 个整数的指针,它是堆栈上的 16 个整数。我们根本无法重新定位a。

如果您需要可调整大小的数组,则需要使用分配:

MyClass* array = new MyClass[10];
MyClass::expand_array(array, 10, 20);
delete [] array;

这就是说,我想指出这种方法很糟糕,因为它会将指针暴露给消费者。相反,您应该将跟踪大小和数组当前存储的位置移到您的 MyClass 类中。不妨看看std::vector

但总的来说,更像这样:http://ideone.com/4hgri4

#include <functional>
#include <cstdint>
#include <iostream>

// CAVEAT EMPTOR: This is a partial, naive implementation,
// it lacks copy/move constructor, operator=, iterators and
// many other things. It is solely intended to demonstrate
// internalizing the paired-state components of size and data
// to provide a discrete encapsulation of the concept of a
// dynamically sized array-like allocation.

class MyArray
{
    // create an alias for the type we're using,
    // this will come in handy when you learn templates.
    typedef int value_type;

    value_type* m_data;
    size_t m_size;

public:
    MyArray() : m_data(nullptr), m_size(0) {}
    MyArray(size_t defaultSize) : m_data(nullptr), m_size(0)
    {
        resize(defaultSize);
    }

    void resize(size_t newSize)
    {
        if (newSize > size()) {
            value_type* newData = new value_type[newSize];
            if (m_data) {
                std::copy(m_data, m_data + size(), newData);
                delete [] m_data;
            }
            m_data = newData;
        }
        m_size = newSize;
        if (m_size == 0 && m_data) {
            delete [] m_data;
            m_data = nullptr;
        }
    } 

    value_type operator[](size_t index) const { return m_data[index]; }
    value_type& operator[](size_t index) { return m_data[index]; }

    size_t size() const { return m_size; }

    void push_back(value_type newValue)
    {
        resize(m_size + 1);
        m_data[size() - 1] = newValue;
    }
};

int main()
{
    MyArray a;
    a.resize(4);
    for (size_t i = 0; i < a.size(); ++i) {
        a[i] = i;
    }

    a.push_back(10);

    std::cout << "Values:\n";
    for (size_t i = 0; i < a.size(); ++i) {
        std::cout << i << ": " << a[i] << '\n';
    }

    return 0;
}

有关数组指针等效性的更多信息,请参阅C++ FAQ section on it。

【讨论】:

  • 我已经在代码的其他地方使用了这种精确的方法:MyClass* array = new MyClass[10]; MyClass::expand_array(array, 10, 20); delete [] array;。但它不起作用。
  • @EMBLEM “它不工作”是什么意思?您需要详细说明,以便我们为您提供帮助。
  • @0x499602D2 代码无法编译并出现问题中显示的错误消息。
  • @kfson 数组不会衰减为指针但将其绑定到引用会失败,因为指针是临时的(右值)并且引用只接受左值?
  • @0x499602D2 请忽略我之前的声明,给我一点时间来编译。我使用的是静态数组,而不是指向其中的指针,这是我的问题的原因。
【解决方案2】:

扩展数组的第一个参数定义为myclass *&,看代码我觉得需要改成myclass * * 并调整调用代码。我猜你正在声明 myclass a[10] 并试图传递它,这永远不会起作用 - 如果你要删除它,你必须传递一个用 new 分配的数组。

【讨论】:

  • 如果是MyClass*,他将无法为其分配数组。
  • 我试过这样,还是编译不出来。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多