c ++中数组的长度

时间:2009-12-25 15:54:56

标签: c++ arrays

我读到了用C ++获取数组的长度,你这样做:

int arr[17];
int arrSize = sizeof(arr) / sizeof(int);

我试着为字符串做同样的事情: 我在哪里

string * arr;
arr = new (nothrow) string [213561];

然后我做

arr[k] = "stuff";

我遍历每个索引并将“stuff”放入其中。

现在我想要数组的大小应该是213561,这是正确的方法,为什么它在C ++中如此复杂?

8 个答案:

答案 0 :(得分:8)

您尝试做的事情无法正常工作,因为sizeof在编译时适用于类型(并且指针类型永远不会占用它们可能指向的数组的大小)。

在您的情况下,计算sizeof(arr)返回指针在内存中占用的大小,而不是

size of the array * size of a std::string

我建议你使用这两个选项中的一个

  • 使用固定大小的数组(sizeof works)
  • 或向量(myVector.size()返回您需要的内容)

......除非你有充分理由不这样做。

答案 1 :(得分:6)

在C ++中执行此操作的正确方法是使用vector。这样,您既可以预先指定大小,也可以随时调整大小。

预先指定尺寸:

using namespace std;
vector<string> arr(213561);

for (vector<string>::iterator p = arr.begin(); p != arr.end(); ++p)
{
  *p = "abc";
}

随时展开向量:

using namespace std;
vector<string> arr;  // <-- note, default constructor

for (int i = 0; i < 213561; ++i)
{
  // add elements to the end of the array, automatically reallocating memory if necessary
  arr.push_back("abc");
}

无论哪种方式,都可以找到数组的大小:

size_t elements = arr.size();  // = 213561

答案 2 :(得分:1)

sizeof方法只有在您的数组实际上是数组时才有效,即具有数组类型的对象。在您的第一个示例中,对象arr的类型为int[17]。它是一种数组类型,这意味着您可以使用sizeof方法并获得17作为结果。

将数组类型T[N]转换为指针类型T *后,基本上会丢失数组类型。应用于指针的sizeof方法不会计算为原始数组的大小。

当您使用T[N]分配类型为new[]的数组时,结果会立即显示类型为T *的指针。它从一开始就不是数组类型。有关数组大小的信息会立即丢失,尝试使用带有此类指针的sizeof方法将无法正常工作。为了保留有关动态分配的运行时大小数组的大小信息,您必须自己将其存储在单独的变量中。

答案 3 :(得分:1)

以下是查找数组大小的方法:

const size_t ARRAY_SIZE = 17;
int array[ARRAY_SIZE];
//...
std::cout << "My array size is: " << ARRAY_SIZE << "\n";

您可以将ARRAY_SIZE放入标题中,以便其他翻译单元可以访问数组大小。

如果您想要一个根据需要增长的动态数组,请尝试std::vector

答案 4 :(得分:0)

您需要使用单独的变量跟踪长度。没有办法得到你只有指针的区域的长度,除非你把它存储在某个地方。

答案 5 :(得分:0)

您无法获得已分配数组的长度。 您可以做的是在分配时单独保存..

另外,你可以使用strlen()检查字符串的长度(这不是你要求的,但仍然是......)

答案 6 :(得分:0)

在c ++中,arr只是对数组第一个元素的引用。如果是动态数组,则无法实现。

答案 7 :(得分:0)

C和C ++都有一个微妙的细微差别,内存分配。这两种语言都不支持动态数组。以下是您所看到的:

int ary[17];
int arrSize = sizeof(ary) / sizeof(ary[0]);

这里ary是一个包含17个整数的真数组。数组大小计算有效,因为sizeof(ary)返回为整个数组分配的内存块的大小。你将它除以每个元素的大小,violà你有数组中元素的数量。

std::string * arr;
arr = new (std::nothrow) std::string[213561];

在这种情况下,arr是指向某个内存的指针。 new运算符分配一块足够大的内存块来容纳213,561个连续std::string个对象,并将它们构造到内存中。 arr变量只是指向内存块的开头。 C ++不跟踪已分配的元素数。你并没有真正创建一个动态数组 - 相反,你为一堆连续的对象分配了足够的内存。

C和C ++都允许您将下标运算符应用于指针作为语法糖。您会看到很多关于arr[0]如何转化为*(arr + 0)的评论。实际情况是,使用new运算符分配内存会导致内存块完全不是数组。语法糖使它看起来像一个。接下来你将遇到的是多维数组是相似的糖。

请考虑以下代码段。一旦你理解了那里发生了什么,你将更加接近理解记忆的运作方式。这就是为什么C和C ++无法告诉你如果动态分配数组有多大的主要原因 - 它不知道大小,所有它都是指向已分配内存的指针。 / p>

#include <iostream>

int
main()
{
    //
    // The compiler translates array subscript notation into
    // pointer arithmetic in simple cases so "hello"[3] is
    // is translated into *("hello" + 3).  Since addition is
    // commutative, the order of "hello" and 3 are irrelevant.
    //
    std::cout
        << "\"hello\"[3] = '" << "hello"[3] << "'\n"
        << "3[\"hello\"] = " << 3["hello"]  << "\n"
        << std::endl;

    //
    // All memory is linear in C or C++.  So an 3x3 array of
    // integers is a contiguous block of 9 integers in row
    // major order.  The following snippet prints out the 3x3
    // identity matrix using row and column syntax.
    //
    int ary[3][3] = { { 1, 0, 0 },
                      { 0, 1, 0 },
                      { 0, 0, 1 } };
    for (int r=0; r<3; ++r) {
        for (int c=0; c<3; ++c) {
            std::cout << "\t" << ary[r][c];
        }
        std::cout << "\n";
    }
    std::cout << "\n";

    //
    // Since memory is linear, we can also access the same
    // 3x3 array linearly through a pointer.  The inner loop
    // is what the compiler is doing when you access ary[r][c]
    // above - "ary[r][c]" becomes "*(ptr + (r * 3) + c)"
    // since the compiler knows the dimensions of "ary" at
    // compile time.
    // 
    int *ptr = &ary[0][0];
    for (int i=0; i<9; ++i) {
        ptr[i] = i;
    }
    for (int r=0; r<3; ++r) {
        for (int c=0; c<3; ++c) {
            std::cout << "\t" << *(ptr + (r * 3) + c);
        }
        std::cout << "\n";
    }

    return 0;
}