C++-Golang的数组类型异同

1. 本文章的必要性

C++的存在像一把瑞士军刀,继承了C语言的设计理念——“充分相信程序员”,几乎将所有的底层细节都暴露在外,程序员可以自由控制。在最近详细学习Golang的过程中,发现Golang中的常用结构的设计理念与C++截然不同,为许多常用的操作都提供了语言设计者所认为的“最佳实践”。本文章仅讨论Golang中数组和切片。

2. Golang数组 和 C++数组(Array)

例子

C++ version

// const常量长度初始化
// 显然非常量无法作为初始化的长度,因为编译器在编译期无法确定要为此数组分配的内存长度
const int len = 10;
int cpp_arr[len];

// 初始化赋值
int cpp_arr[] = {1, 2, 3, 4, 5};

Golang version

// const常量长度初始化
// 显然非常量无法作为初始化的长度,理由同上
const len := 10
var golang_arr [len]int

// 初始化赋值
golang_arr := [...]int{1, 2, 3, 4, 5}

// Golang额外提供了语法,用于初始化数组为同一元素
// 将golang_arr初始化为具有100个元素-1的数组
golang_arr := [...]int{100:-1}

内存模型

两者一样,都是线性的内存结构。数组的本质,即为编译器在编译期在数据段分配常量长度的内存,再填充上指定的数据。从这方面很容易理解,两者的数组的长度是不容许修改的。

参数传递

C++ version
C++的数组传参都只能靠指针
但对于指针的移动偏移无任何限制,只能靠程序员手动管理,如果读写越界,可能会破坏堆栈

int passArray(int arr[])
{
    // 合法
    arr[0] = 0;
    // 不合法!可能会破坏进程地址空间中的内存布局
    arr[-1000] = 0;
}

int main()
{
    int arr[] = {1, 2, 3, 4, 5};
    passArray(&arr[0]);
    return 0;
}

golang version

// 通过改变ptr的指向,将ptr所指的内存置为空
// 原来的内存,GC可通过引用计数探测,将其释放
func passArrayByPointer(ptr *[32]int) {
  *ptr = [32]int{}
}

// 无效,只是对拷贝进行了一次赋值
func passArrayByValue(arr [32]int) {
    arr = [32]int{}
}
  • Golang对C++传递数组进行了限制和优化,将数组类型作为函数的形参时,必须显式的指定该数组的长度。在编译期,编译器也会对传入数组的长度与声明的长度进行比对,如果不相等则无法编译通过。
  • 和其他高级语言不同(比如Java),语言中内置的类型有的为引用类型(在作为函数参数时直接传递引用),有的为值类型(在作为函数参数时传递一份拷贝),Golang在这方面引入了指针,可以自由控制给函数传递的数组是拷贝,还是指针(这是传参时,与C++最大的不同)

    总结

  1. 语法格式不同(废话)
  2. 作为参数传递时,长度Golang有严格的长度检查机制,防止写坏内存
  3. Golang中的数组是值语义,数组名即代表整个数组,而不像C/C++隐含为第一个元素的地址

  4. 内存布局一致
  5. 分配特性一致,即数组长度在编译期即确定,无法改变

原文地址:https://www.cnblogs.com/jo3yzhu/p/11047177.html

时间: 2024-11-06 16:17:07

C++-Golang的数组类型异同的相关文章

学习Golang语言(6):类型--切片

学习Golang语言(1): Hello World 学习Golang语言(2): 变量 学习Golang语言(3):类型--布尔型和数值类型 学习Golang语言(4):类型--字符串 学习Golang语言(5):类型--数组 学习Golang语言(6):类型--切片 在很多应用场景中,数组不能够满足我们的需求.在初始定义数组时,我们并不知道数组所需的长度.因此,我们需要一个大小可以动态变化的数组(动态数组) 在Go语言中,这种"动态数组"成为slice(切片). 但是实际上slic

C++数组类型与函数类型

之所以将C++的数组类型与函数类型拿到一块说,是因为两者在很多地方都一样. 首先,声明形式上类似: 数组类型:  type [num]                                          数组:type name[num] 函数类型:  return_type (形参列表)    函数:return_type name(形参列表) 数组指针类型: type (*)[num] 数组指针:type (*name)[num] 函数指针类型: return_type (*)

使用typedef语句定义数组类型

使用typedef语句定义数组类型     1. 一维数组类型的定义格式 typedef <元素类型关键字><数组类型名>[<常量表达式>]; 例如: (1) typedef int vector[10]; (2) typedef char strings[80]; (3) typedef short int array[N]; 第一条语句定义了一个元素类型为int,含有10个元素的数组类型vector,若不使用typedef保留字,则就变成了数组定义,它只定义了一个元

怎么判断一个对象是不是数组类型?

前面<变量的赋值和对象的赋值>中有用到typeof运算符去判断运算数的类型,结果如下: alert(typeof 1); // 返回字符串"number" alert(typeof "1"); // 返回字符串"string" alert(typeof true); // 返回字符串"boolean" alert(typeof {}); // 返回字符串"object" alert(typeof

《JS权威指南学习总结--7.10 数组类型》

内容要点: 一.数组类型 判断它是否为数组通常非常有用.在ES5中,可以使用Array.isArray()函数来做这件事情: Array.isArray([]); //=>true Array.isArray({}); //=>false 二.类数组对象 JS数组的有一些特性是其他对象所没有的: 1.当有新的元素添加到列表中时,自动更新length属性. 2.设置length为一个较小值将截断数组. 3.从Array.prototype中继承一些有用的方法. 4.其类属性为"Arra

Java-第十四章-代参的方法(二)-编程实现,输入班里10名学生的身高,获得身高最高的学生要求对象数组类型方法

package com.ww.yzpA; public class Students { int No; int Height; } package com.ww.yzpA; public class Height { public Students getMaxHeigth(Students[] str) { Students A = new Students(); for (int i = 0; i < str.length; i++) { if (str[i].Height > A.He

postgresql 数组类型初步实践

实践环境 数据库:postgresql 9.4:操作系统:windows 创建包含数组类型的数据库 注意在设置default 值时(当然你可以不指定默认值),要声明数组的类型,像这样声明"::bigint[]". create table testarray( id serial primary key, images bigint[] default array[]::bigint[] ); 插入数组值 注意插入数组时,也要声明数组的类型,同上 insert into testarr

判断一个变量是数组类型的方法

在很多时候,我们都需要对一个变量进行数组类型的判断(借鉴) 学过js就应该知道typeof运算符返回字符串,该字符串代表操作数的类型(即返回数据类型)这是最常用的. 下面多种实现方式: JavaScript中检测对象的方法 1.typeof操作符 这种方法对于一些常用的类型来说那算是毫无压力,比如Function.String.Number.Undefined等,但是要是检测Array的对象就不起作用了. alert(typeof null); // "object" alert(ty

记录struts2 json plugin 对字符串数组类型的处理

当前项目中,一开发人员在action中定义了一个字符串数组类型的属性,需要以json格式返回到页面(先不论这种设计是否最优), 结果在做页面调试时发现总是无法在ajax的success方法中获取到该属性.后台action调试发现该数组已经正确赋值,get 方法也没有问题,action相关代码如下: private String[] traceList; private String unitName; ... public String queryTrace(){ unitName = "tes