如何在C++或 Java 中"copied"数组
How is array being "copied" in C++ or Java
基本上,问题是编译器如何管理内存。
double[] b = {1.0, 2.0, 3.0};
double[] a = new double[3]; //for Java
double a[3]; //for C++
a = b;
当声明数组a
时,24字节的内存空间被分配给数组a
。
a=b
简单地将数组b
的引用的值复制到a
。
24字节的内存块呢?它将立即释放,还是在函数/方法结束时回收?
当数组a被声明时,24字节的内存空间被分配给数组a。
在C++中。在Java中,只有一个引用在声明中分配,数组本身在初始化器中分配。
a=b简单地将数组b的参考值复制到a。
在Java中。在C++中,它不是合法代码。
24字节的内存块呢?它将立即释放,还是在函数/方法结束时回收?
在C++中,它随着封闭作用域或更可能的封闭方法而消失。在Java中,当对它的最后一次引用消失时,它就有资格进行垃圾收集,在本例中,这就是方法的结束。
你的问题真的太复杂了,没有什么意义。试着一次用一种语言思考。
Java在变量超出范围时运行垃圾收集器。在这种情况下,如果函数中的最后一个方法是a = b
,并且代码中没有其他对a
或b
的引用,Java将取消分配用于数组的内存。
在C++中,在执行时,以下代码片段将提供错误作为无效的数组赋值
a = b;
使用的代码段:
double b[] = {1.0, 2.0, 3.0};
double a[3]; //for C++
a = b; // error: invalid array assignment
相反,你必须做:
memcpy(a, b, sizeof(a));
在C++中,数组有一个固定的起始(基)地址,不能重新分配。在Java中,数组类似于C++中的指针(在Java中称为引用),因此可以进行赋值。
在C++中,您的代码将无法工作;要么你必须有这样的东西:
#include <iostream>
#include <algorithm>
int main() {
int b[] = { 4, 5, 6 };
int a[3];
std::copy_n(std::begin(b), std::end(a)-std::begin(a), std::begin(a));
// the above is safer than just
// std::copy(std::begin(b), std::end(b), std::begin(a))
// in the case that the size of b is greater than the size of a...
a[2] = 9;
std::cout << b[2] << ' ' << a[2] << 'n';
}
(在这种情况下,a
和b
的存储器都在堆栈上)或其较新的C++11等价物:
#include <iostream>
#include <memory>
int main() {
std::array<int, 3> b { 4, 5, 6 };
auto a = b; // or std::array<int, 3> a = b;
a[2] = 9;
std::cout << b[2] << ' ' << a[2] << 'n';
}
或者,如果您想要像java那样的可调整大小的数组,则必须使用vector
:
#include <iostream>
#include <vector>
int main() {
std::vector<int> b { 4, 5, 6 };
auto a = b;
a[2] = 9;
std::cout << b[2] << ' ' << a[2] << 'n';
}
在所有情况下,正如您在运行示例时所看到的,数组都是逐项复制的(所有三个示例都打印6 9
),因此每个数组的存储将占用三个int
变量(或24字节,在64位机器中)的空间——加上最后一种情况下vector
的开销。。。
回答您的问题:在前两种情况下,当24个字节在堆栈上分配时,它会在返回时自动释放。在最后一种情况下,std::vector
的析构函数也负责释放堆上的内存。
EDIT:我忘了举一个例子,在Java中,a
只是对与b
:相同的底层存储的引用的副本
#include <iostream>
#include <memory>
int main() {
std::array<int, 3> b { 4, 5, 6 };
auto& a = b; // or std::array<int, 3>& a = b;
a[2] = 9;
std::cout << b[2] << ' ' << a[2] << 'n';
}
(这也适用于vector
,运行时会打印9 9
)
在Java 中
double[] b = {1.0, 2.0, 3.0};
double[] a = new double[3];
a = b;
a
的声明不会导致24字节的内存块分配。仅创建一个引用变量。
在C++中,代码应该是
void myArray(double a[], int size_a){
double c = 4.0;
a = &c;
cout << *a;
}
int main(){
double b[] = {1.0, 2.0, 3.0};
myArray(b, 3);
return 0;
}
在这种情况下,a
是一个指针。不是将整个数组传递给函数,而是仅将数组的起始地址复制到a
。
简而言之,在这两种语言中,只有一个数组在内存中创建。经过上述操作后,程序不会变得繁琐。
- Mongodb c++驱动程序:如何查询元素的数组
- 将数组的地址分配给变量并删除
- 从C++本机插件更新Vector3数组
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 数组索引的值没有增加
- 将对象数组的引用传递给函数
- 为char数组调整zlib-zpipe
- 2D数组来自文本输入,中间有空格
- std::向量与传递值的动态数组
- 在c++中用vector填充一个简单的动态数组
- 使用strcpy将char数组的元素复制到另一个数组
- 使用指针从C++中的数组中获取最大值
- C++使用整数的压缩数组初始化对象
- 告诉一个 const char 数组,除了编译时 C 样式的字符串外,它不以 '