数组的大小

发布于 2024-08-14 06:34:38 字数 1000 浏览 9 评论 0原文

这个问题是关于 C++ 的,

我一直认为 C++ 中数组的名称只是一个指针,所以我认为这

int ar[10];
cout << sizeof(ar);

会给我与 sizeof(int *) 相同的结果。但它给出了 40 - 所以它是整个数组的实际大小。当数组大小由变量给出时,它也给出 40:

int n = 10;
int ar[n]

我想复制一个包含数组的类。如果它是用运算符 new 分配的,那么我应该在复制构造函数中手动复制该数组。但是恒定大小的数组又如何呢?类只包含一个指向数组的指针,还是包含整个数组?简单的 memcpy(...) 这里安全吗?

编辑: 另一个例子:

int n;
cin >> n;
int ar[n];
cout << sizeof(ar);

它打印 n*4。我在 Linux 上使用 g++。

我什至尝试了这个:

class Test {
public:
    int ar[4];
};

并且

Test a, b, c;
a.ar[0] = 10;
b = a;
memcpy(&c, &a, sizeof(a));
a.ar[0] = 20;
cout << "A: " << a.ar[0] << endl;
cout << "B: " << b.ar[0] << endl;
cout << "C: " << c.ar[0] << endl;

它给出了:

A: 20
B: 10
C: 10

所以数组被存储为类的一部分,并且可以使用 memcpy 进行复制。但这安全吗?

This question is about C++

I always thought that name of an array in C++ is only a pointer, so I thought that

int ar[10];
cout << sizeof(ar);

will give me the same as sizeof(int *). But it gives 40 - so it is real size of whole array. It also gives 40 when array size is given by variable:

int n = 10;
int ar[n]

I want to copy a class that contains an array. If it would be allocated with operator new then I should manualy copy this array within a copy constructor. But how about constant sized arrays? Does class contains only a pointer to an array, or does it contains whole array? Is simple memcpy(...) safe here?

EDIT:
Another example:

int n;
cin >> n;
int ar[n];
cout << sizeof(ar);

and it prints n*4. I'm using g++ on linux.

I even tried this:

class Test {
public:
    int ar[4];
};

and

Test a, b, c;
a.ar[0] = 10;
b = a;
memcpy(&c, &a, sizeof(a));
a.ar[0] = 20;
cout << "A: " << a.ar[0] << endl;
cout << "B: " << b.ar[0] << endl;
cout << "C: " << c.ar[0] << endl;

and it gives:

A: 20
B: 10
C: 10

So array is stored as a part of a class and can be copied with memcpy. But is it safe?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

丶情人眼里出诗心の 2024-08-21 06:34:38

数组不是指针。当/如果将数组作为参数传递给函数时,数组的名称会“衰减”为指针 - 但 sizeof 是语言中内置的运算符,而不是函数,因此 sizeof(array) 只要应用于实际数组,就会生成数组的实际大小(而不是作为参数传递数组的名称,然后使用 sizeof() 在传递给函数时衰减到的指针上,

就复制包含数组的类而言,如果它确实是一个数组,例如:

class X { 
    int x[10];
};

那么您不需要执行任何操作即可复制它 - - 编译器可以/将生成一个复制构造函数来复制数组的内容如果(且仅当)您实际上有一个指针,并自己分配空间,您是否需要编写一个复制构造函数来执行“深度复制”。 “(即在新对象中分配空间,并复制指针指向的数据)。但是,您通常应该使用 std::vector,而不是这样做,它在内部完成所有这些操作所以你不用担心。

An array is not a pointer. The name of an array "decays" to a pointer when/if you pass it as a parameter to a function -- but sizeof is an operator built into the language, not a function, so sizeof(array) yields the actual size of the array as long as it's applied to the actual array (as opposed to the name of the array being passed as a parameter, then using sizeof() on the pointer that it decayed to when it was passed to the function.

As far as copying a class that contains an array, if it's really an array, like:

class X { 
    int x[10];
};

Then you don't need to do anything for it to be copied -- the compiler can/will generate a copy constructor that copies the contents of the array. If (and only if) you actually have a pointer, and allocate the space yourself, do you need to write a copy ctor to do a "deep copy" (i.e. allocate space in the new object, and copy the data pointed TO by the pointer). Rather than doing this, however, you should normally use an std::vector, which does all that internally so you don't have to worry about it.

凉宸 2024-08-21 06:34:38

一次服用这些:

我想复制一个包含数组的类。

好的,例如:

class Foo
{
    int arr[20];
};

如果它是用operator new分配的,那么我应该在复制构造函数中手动复制这个数组。

好的,现在混乱开始了。在上面的示例中,数组实际上是对象的一部分。如果 int 是 4 个字节,则 sizeof(Foo) 将为您提供 80。

另一种方法是使用指向数组的指针,如果数组需要更改大小,这会很有用:

class Bar
{
    int *arr;
};

在这种情况下,sizeof(Bar) 是指针的大小(通常为 4 或 8 字节) ),复制对象也会复制指针。这称为“浅复制”。如果您想要一个“深层复制”,即复制将复制数组的内容而不仅仅是对象,那么您需要一个复制构造函数。

第三种替代方法是使用 vector,正如 wheaties 所建议的:

class Bob
{
    std::vector<int> arr;
};

这在内部工作原理与 Bar 情况相同,并且 vector 可以调整大小,但是 vector 模板会为您处理深层复制,因此您不需要复制构造函数。

如果您需要固定大小的数组(其大小在编译时已知),我建议使用 Foo 情况,否则建议使用 Bob 情况。 Bar 案例几乎只是重新发明轮子。

简单的 memcpy(...) 这里安全吗?

对于 Foo 来说是安全的。如果您想要浅拷贝,对于 Bar 来说是安全的。对于 Bob 来说不安全。

这个故事的寓意是,将变量存储在对象中就像将其存储在功能块或全局中一样:如果您指定一个数组([N] 而不是 *),大小最好在编译时确定,然后你就可以将存储放在那里。

Taking these one at a time:

I want to copy a class that contains an array.

Okay, so for example:

class Foo
{
    int arr[20];
};

If it would be allocated with operator new then I should manualy copy this array within a copy constructor.

Okay, now the confusion sets in. In the above example, the array is actually part of the object. sizeof(Foo) would give you 80 if int is 4 bytes.

An alternative would be to have a pointer to an array, which is useful if the array needs to change size:

class Bar
{
    int *arr;
};

In that case, sizeof(Bar) is the size of a pointer (usually 4 or 8 bytes), and copying the object copies the pointer. This is called a "shallow copy". If you wanted a "deep copy", i.e. a copy would duplicate the array's contents and not just the object, then you need a copy constructor.

The third alternative is to use vector, as wheaties recommends:

class Bob
{
    std::vector<int> arr;
};

This internally works the same as the Bar case, and the vector can be resized, but the vector template takes care of the deep copy for you, so you don't need a copy constructor.

I'd recommend the Foo case if you need a fixed-size array, where the size is known at compile time, and the Bob case otherwise. The Bar case is pretty much just reinventing the wheel.

Is simple memcpy(...) safe here?

Safe for Foo. Safe for Bar if you want a shallow copy. Unsafe for Bob.

The moral of the story is that storing a variable in an object works just like storing it in a function block or global: if you specify an array ([N] instead of *), the size had better be determined at compile time, and you get the storage placed right there.

离不开的别离 2024-08-21 06:34:38

实际上ar一个数组,这就是sizeof()找到实际大小的原因。 C/C++ 中的数组有一个指针(指针表达式或右值)。

int ar[10];
int *p;
p = ar;  // OK
ar = p;  // error 

Actually aris an array, that is why sizeof() finds the actual size. An array in C/C++ has a pointer value (pointer expression or rvalue).

int ar[10];
int *p;
p = ar;  // OK
ar = p;  // error 
恍梦境° 2024-08-21 06:34:38

注释: 在标准 C (C89) 中,您应该只能使用文字或 const 来初始化数组。所以编译器不会感到困惑。

答案:如果你以“栈上方式”初始化一个数组——即不使用new或malloc。该类将封装数组的大小。数组的基数是指针,因为编译器在内部使用指针算术来解析访问运算符[]

如果您使用 new 或 malloc,则必须使用用于分配内存的变量作为您分配的内存大小的最终度量。您可以将 memcpy() 与数组基指针一起使用,因为无论它分配在哪里,它仍然是指向数组基内存位置的指针。

答案 2:问题编辑后

是的,使用相同类型和相同大小的常量大小的数组来执行此操作是完全安全的,但不要使用动态分配的资源执行此操作,除非您正在跟踪它们类型和尺寸。只需避免您正在采用的方法并使用容器类即可。

注意:我回避了您对堆分配内存上的sizeof运算符的观点,因为我无法说出其行为是什么。我是老派,我永远不会在动态资源上使用 sizeof,因为它取决于运行时机制,谁知道不同的编译器供应商包含哪些运行时机制。

然而,我知道,当一个数组被 C++ 中的 new (在大多数编译器上)分配时,它会在数组的底部放置一个物理上的整数。这个整数表示接下来的数组。这就是为什么您必须使用 delete [] 运算符,该运算符与标准 delete 不同,因为它会导致编译器吐出一个循环,该循环反复调用项目的析构函数。如果 C++ 编译器供应商将一个整数放在数组的底部,那么他们可能会在运行时使用它来为 sizeof 运算符提取它。 我不知道标准对此有何规定,并且我怀疑它是否可以这样工作。

测试:Visual Studio 2008

#include "stdafx.h"
#include <iostream>


int _tmain(int argc, _TCHAR* argv[])
{
    int x;
    int *y=new int[5];
    int z[5];
    std::cout << sizeof(x);
    std::cout << " " <<  sizeof(y);
    std::cout << " " << sizeof(z);
    return 0;
}

输出:

4 4 20

您只能在运行时确定数组的大小(如果数组是硬编码的)——即,就像 z 的情况一样。 x 是一个 int ,y 是一个指针,两者的行为都是如此。

Comment : in standard C (C89) you should only be able to initialize an array with a literal or a const. So there is no confusion for the compiler.

Answer : If you initialize an array in the "on the stack way" -- i.e., without using new or malloc. The class would encapsulate the size of the array. The base of an array is a pointer because the compiler uses pointer arithmetic internally to resolve the access operator [].

If you use new or malloc, then you must use variable that you used to allocate memory as the definitive measure of the size of the memory you allocated. you may use memcpy() with the array base pointer, as irrespective of where it is allocated, it is still a pointer to the base memory location of the array.

answer 2: after question edits

Yes it is perfectly safe to do that with const-sized arrays of the same type and of the same size, but do not do it with dynamically allocated resources unless you are tracking their types and sizes. Just avoid the approach you are taking and go with a container class.

Note : I have evaded your point on the sizeof operator on heap allocated memory as I cannot say what the behaviour is. I am old-school and I would never use sizeof on dynamic resources as it depends on runtime machinery, and who knows what runtime machinery different compiler vendors include.

However, I know this, that when an array is alloced by new (on most compilers) in C++ it places a integer -- physically -- at the base of the array. This integer represents the size of the array that follows. This is why you must use the delete [] operator, this operator differs from standard delete because it causes the compiler to spit out a loop which itteratively calls the destructor on your items. If a C++ compiler vendor place an integer at the base of an array than they might use this at runtime to extract it for the sizeof operator. I have no idea what the standard says about it, and I doubt it works this way.

TEST: Visual Studio 2008

#include "stdafx.h"
#include <iostream>


int _tmain(int argc, _TCHAR* argv[])
{
    int x;
    int *y=new int[5];
    int z[5];
    std::cout << sizeof(x);
    std::cout << " " <<  sizeof(y);
    std::cout << " " << sizeof(z);
    return 0;
}

OUTPUT:

4 4 20

You can only determine the size of an array at runtime if its hard-coded -- i.e., like in the case of z. x is an int and y is a pointer both behave as such.

ぺ禁宫浮华殁 2024-08-21 06:34:38

你研究过STL的向量吗?它的行为类似于数组,具有可调整的大小,并且包含一个返回数组大小的函数“size()”。

Have you looked into STL's vector. That behaves similar to an array, has adjustable size, and contains a function "size()" which returns the size of the array.

一个人的旅程 2024-08-21 06:34:38

sizeof(ar) 仅起作用,因为 ar 的声明此时对编译器可见。
数组大小不会被存储,并且在运行时永远不可用,如果您将 ar 传递给函数并执行 sizeof(ar) ,您将得到 4 >。所以基本上你的编译器足够聪明,可以查看上面的几行。

sizeof 是一个编译器关键字,它将在编译时中提供大小。因此,编译器必须能够知道或推断出您正在查看的 var 的大小,以给出正确的大小。

REEDIT:sizeof 是一个编译时常量(C99 可变长度数组除外),编译器可以在其中添加运行时计算。然而,这是 C++ 的编译器扩展,因为 C99 不是 C++ 标准的一部分。

sizeof(ar) only works because the declaration of ar is visible to the compiler at that point.
Array sizes are not stored and never available in runtime, if you pass ar to a function and do sizeof(ar) there you'll get 4. So its basically that your compiler is smart enough to look a couple of lines above.

sizeof is a compiler keyword that will deliver a size in compile time. So the compiler must be able to know, or deduce, the size of the var you are looking at to give the proper size.

REEDIT: : sizeof is a compile-time constant [except for C99 variable-length arrays] where the compiler can add runtime computation. This however is a compiler extension to C++ as C99 is not part of the C++ standard.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文