02-C++数据类型-高级

数据类型-高级

4、复合类型

4.4、结构简介

struct inflatable
{char name[20];float vol;double price;
};inflatable vincent;			//C++
struct inflatable goose;	//C

例子

// structur.cpp -- a simple structure
#include <iostream>
struct inflatable   // structure declaration
{char name[20];float volume;double price;
};int main()
{using namespace std;inflatable guest ={"Glorious Gloria",  // name value1.88,               // volume value29.99               // price value};  // guest is a structure variable of type inflatable
// It's initialized to the indicated valuesinflatable pal ={"Audacious Arthur",3.12,32.99};  // pal is a second variable of type inflatable
// NOTE: some implementations require using
// static inflatable guest =cout << "Expand your guest list with " << guest.name;cout << " and " << pal.name << "!\n";
// pal.name is the name member of the pal variablecout << "You can have both for $";cout << guest.price + pal.price << "!\n";// cin.get();return 0; 
}
/*
Expand your guest list with Glorious Gloria and Audacious Arthur!
You can have both for $62.98!
*/

外部声明可以被其后面的任何函数使用,而内部声明只能被该声明所属的函数使用。通常使用外部声明,这样所有函数都可以使用这种类型的结构。

变量也可以在函数内部和外部定义,外部变量由所有的函数共享。C++不提倡使用外部变量,但提倡使用外部结构的声明。

结构的赋值

可以使用赋值运算符(=)将结构A赋给另一个同类型的结构B。这样结构中每个成员都将被设置成另一个结构中相应成员的值,即使成员是数组。这种赋值被称为成员赋值。

// assgn_st.cpp -- assigning structures
#include <iostream>struct inflatable {char name[20];float volume;double price;
};int main() {using namespace std;inflatable bouquet = {"sunflowers",0.20,12.49};inflatable choice;cout << "bouquet: " << bouquet.name << " for $";cout << bouquet.price << endl;choice = bouquet;  // assign one structure to anothercout << "choice: " << choice.name << " for $";cout << choice.price << endl;// cin.get();return 0;
}
/*
bouquet: sunflowers for $12.49
choice: sunflowers for $12.49
*/

结构体数组

// arrstruc.cpp -- an array of structures
#include <iostream>struct inflatable {char name[20];float volume;double price;
};int main() {using namespace std;inflatable guests[2] = {        // initializing an array of structs{"Bambi", 0.5, 21.99},      // first structure in array{"Godzilla", 2000, 565.99}  // next structure in array};cout << "The guests " << guests[0].name << " and " << guests[1].name<< "\nhave a combined volume of "<< guests[0].volume + guests[1].volume << " cubic feet.\n";// cin.get();return 0;
}
/*
The guests Bambi and Godzilla
have a combined volume of 2000.5 cubic feet.
*/

结构中的位字段

与C语言一样,C++也允许指定占用特定位数的结构成员,这使得创建于某个硬件设备上的寄存器对应的数据结构非常方便。

struct torgle_register
{unsigned int SN :4;unsigned int :4;bool goodIn:1bool goodTorgle:1;
}

4.5、共用体

共同体是一种数据格式,它能够存储不同的数据类型,但只能同时存储其中的一种类型。也就是说,结构可以同时存储int、long、double,共用体只能存储int、long或double。

union one4all
{int int_val;long long_val;double double_val;
};struct widget
{char brand[20];int type;union id{long id_num;char id_char[20];}id_val;
};
widget prize;
if(prize.type==1)cin>>prize.id_val.id_num;
elsecin>>prize.id_val.id_char;//匿名共用体没有名称,其成员将成为位于相同地址处的变量
struct widget
{char brand[20];int type;union {long id_num;char id_char[20];};
};
widget prize;
if(prize.type==1)cin>>prize.id_num;
elsecin>>prize.id_char;

4.6、枚举

enum spectnum{red, orange, yellow, green, blue, violet, indigo, yyuu};spectnum band;
band=blue;			//valid
band=2000;			//invalidband=orange;		//valid
++band;				//invalid
band=orange + red;	//invalidint color =blue;	//valid
band =3;			//invalid
color=3+red;		//valid, red converted to intband = spectnum(3);	//强转

枚举的取值范围

enum bits{one=1, two=2, four=4, eight=8};
bits myflag;
myflag=bits(6);		//valid,because 6 is in bits range

范围,最大值、最小值所对应的2次幂-1(负数:+1)

4.7、指针和自由存储空间

// address.cpp -- using the & operator to find addresses
#include <iostream>int main() {using namespace std;int donuts = 6;double cups = 4.5;cout << "donuts value = " << donuts;cout << " and donuts address = " << &donuts << endl;
// NOTE: you may need to use unsigned (&donuts)
// and unsigned (&cups)cout << "cups value = " << cups;cout << " and cups address = " << &cups << endl;// cin.get();return 0;
}
/*
donuts value = 6 and donuts address = 0x62fe1c
cups value = 4.5 and cups address = 0x62fe10
*/

指针与C++基本原理

面向对象编程与传统的过程性编程的区别在于,OOP强调的是在运行阶段(而不是编译阶段)进行决策。运行阶段指的是程序正在运行时,编译阶段指的是编译器将程序组合起来时。运行阶段觉得就好比度假时,选择参观哪些景点取决于天气和当时的心情;而编译阶段决策更像不管在什么条件下,都坚持预先设定的日程安排。总之,使用OOP时,可能在运行阶段吧确定数组的长度。为使用这种方法,语言必须允许在程序运行时创建数组。C++采用的方法是,使用关键字new请求正确数量的农村以及使用指针来跟踪新分配的内存的位置。在运行阶段做决策并非OOP独有的,但使用C++编写这样的代码比使用C语言要简单很多。

指针表示的是地址。*运算符被称为间接值或解除引用运算符,将其应用与指针,可以得到该地址处存储的值。

// pointer.cpp -- our first pointer variable
#include <iostream>int main() {using namespace std;int updates = 6;        // declare a variableint *p_updates;         // declare pointer to an intp_updates = &updates;   // assign address of int to pointer// express values two wayscout << "Values: updates = " << updates;cout << ", *p_updates = " << *p_updates << endl;// express address two wayscout << "Addresses: &updates = " << &updates;cout << ", p_updates = " << p_updates << endl;// use pointer to change value*p_updates = *p_updates + 1;cout << "Now updates = " << updates << endl;// cin.get();return 0;
}
/*
Values: updates = 6, *p_updates = 6
Addresses: &updates = 0x62fe14, p_updates = 0x62fe14
Now updates = 7
*/

对于指针,&取地址运算符;*解除引用运算符。有以下的图

在这里插入图片描述

指针初始化

int * p_updates;int *ptr;		//*ptr是一个int类型的值
int* ptr; 		//指针ptr指向int类型;ptr的类型是指针int的指针int* p1,p2;		//一个指针(p1)和一个int变量(p2)double* tax_ptr;//指向double的指针
char* str;		//指向char的指针

**注意:**在C++中,int*是一种复合类型,是指向int的指针

和数组一样,指针都是基于其他类型的。虽然tax_ptr和str指向两种长度不同的数据类型,但这两个变量本身的长度通常是相同的。也就是说,char的地址和double的地址的长度相同。

可以在声明语句中初始化指针。

//被初始化的是指针,而不是它指向的值
int higgens=5;
int* pt=&higgens;
// init_ptr.cpp -- initialize a pointer
#include <iostream>int main() {using namespace std;int higgens = 5;int *pt = &higgens;cout << "Value of higgens = " << higgens<< "; Address of higgens = " << &higgens << endl;cout << "Value of *pt = " << *pt<< "; Value of pt = " << pt << endl;// cin.get();return 0;
}/*
Value of higgens = 5; Address of higgens = 0x62fe14
Value of *pt = 5; Value of pt = 0x62fe14
*/

指针的危险

在C++中创建指针时,计算机将分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存。为数据提供空间是一个独立的步骤。

long *fwllow;
*fwllow=23455556;	//invalid

警告

一定要在对指针应用解除引用运算符(*)之前,将指针初始化为一个确定的、适当的地址。

int* pt;
pt=0xB8000000;			//type mismatch
//要将数字值作为地址来使用,应通过强制类型转换将数字转换为适当的地址类型
pt=(int*)0xB8000000;	//type now match

new&delete

  • 可以使用new来分配内存
//方式1
int* pn=new int;//方式2
int higgens;
int* pt=&higgens;

都是将一个int变量的地址赋给了指针。第2种情况下,可以通过名称higgens来访问该int,在第1种情况下,只能通过该指针进行访问。

// use_new.cpp -- using the new operator
#include <iostream>
int main() 
{using namespace std;int nights = 1001;int *pt = new int;          // allocate space for an int*pt = 1001;                 // store a value therecout << "nights value = ";cout << nights << ": location " << &nights << endl;cout << "int ";cout << "value = " << *pt << ": location = " << pt << endl;double *pd = new double;    // allocate space for a double*pd = 10000001.0;           // store a double therecout << "double ";cout << "value = " << *pd << ": location = " << pd << endl;cout << "location of pointer pd: " << &pd << endl;cout << "size of pt = " << sizeof(pt);cout << ": size of *pt = " << sizeof(*pt) << endl;cout << "size of pd = " << sizeof pd;cout << ": size of *pd = " << sizeof(*pd) << endl;// cin.get();return 0;
}
/*
nights value = 1001: location 0x62fe14
int value = 1001: location = 0x26d6710
double value = 1e+07: location = 0x26d6cf0
location of pointer pd: 0x62fe08
size of pt = 8: size of *pt = 4
size of pd = 8: size of *pd = 8
*/
  • 使用delete释放内存
int* ps= new int;		//allocate memory with new
....					//use the memory
delete ps;				//free memory with delete when done

这将释放ps指向的内存,但不会删除指针ps本身。例如,可以将ps重新指向另一个新分配的内存块。一定要配对得使用new和delete。

不要尝试释放已经释放的内存块。另外,不能使用delete来释放声明变量所获得的内存:

int *ps=new int;
delete ps;
delete ps;	//not ok nowint jugs=5;
int* pi=&jugs;	//ok
delete pi;		//not allowed

警告:

智能用delete来释放使用new分配的内存。然而,对空指针使用delete是安全的。

int* ps=new int;
int* pq=ps;
delete pq;

一般来说,不要创建两个指向同一个内存块的指针,因为这将增加错误地删除同一个内存块两次的可能性。

  • 使用new来创建动态数组
int* psome=new int[10];
delete [] psome;
//分配内存的通用格式
type_name* pointer_name =new type_name[size];

使用new和delete时,应遵守以下规则

  1. 不要使用delete来释放不是new分配的内存
  2. 不要使用delete释放同一个内存块两次
  3. 如果使用new[]为数组分配内存,则应使用delete[]来释放
  4. 如果使用new为一个实体分配内存,则应使用delete(没有方括号)来释放
  5. 对空指针应用delete是安全的
// arraynew.cpp -- using the new operator for arrays
#include <iostream>int main() {using namespace std;double *p3 = new double [3];  // space for 3 doublesp3[0] = 0.2;                  // treat p3 like an array namep3[1] = 0.5;p3[2] = 0.8;cout << "p3[1] is " << p3[1] << ".\n";p3 = p3 + 1;                  // increment the pointercout << "Now p3[0] is " << p3[0] << " and ";cout << "p3[1] is " << p3[1] << ".\n";p3 = p3 - 1;                  // point back to beginningdelete [] p3;                 // free the memory// cin.get();return 0;
}
/*
p3[1] is 0.5.
Now p3[0] is 0.5 and p3[1] is 0.8.
*/

不能修改数组名的值,但指针时变量,可以修改它的值。

4.8、指针、数组和指针算术

指针和数组等价的原因在于指针算术和C++内部处理数组的方式。

C++将数组名解释为地址。

// addpntrs.cpp -- pointer addition
#include <iostream>int main() {using namespace std;double wages[3] = {10000.0, 20000.0, 30000.0};short stacks[3] = {3, 2, 1};// Here are two ways to get the address of an arraydouble *pw = wages;      // name of an array = addressshort *ps = &stacks[0];  // or use address operator =stacks 
// with array elementcout << "pw = " << pw << ", *pw = " << *pw << endl;pw = pw + 1;cout << "add 1 to the pw pointer:\n";cout << "pw = " << pw << ", *pw = " << *pw << "\n\n";cout << "ps = " << ps << ", *ps = " << *ps << endl;ps = ps + 1;cout << "add 1 to the ps pointer:\n";cout << "ps = " << ps << ", *ps = " << *ps << "\n\n";cout << "access two elements with array notation\n";cout << "stacks[0] = " << stacks[0]<< ", stacks[1] = " << stacks[1] << endl;cout << "access two elements with pointer notation\n";cout << "*stacks = " << *stacks<< ", *(stacks + 1) =  " << *(stacks + 1) << endl;cout << sizeof(wages) << " = size of wages array\n";cout << sizeof(pw) << " = size of pw pointer\n";// cin.get();return 0;
}
/*
pw = 0x62fdf0, *pw = 10000
add 1 to the pw pointer:
pw = 0x62fdf8, *pw = 20000ps = 0x62fdea, *ps = 3
add 1 to the ps pointer:
ps = 0x62fdec, *ps = 2access two elements with array notation
stacks[0] = 3, stacks[1] = 2
access two elements with pointer notation
*stacks = 3, *(stacks + 1) =  2
24 = size of wages array
8 = size of pw pointer
*/

对于指针的加法

在这里插入图片描述

注意:

将指针变量加1后,其增加的值等于指向的类型占用的字节数。

通常,使用数组表示法时,C++都执行下面的转换

arrayname[i] becomes *(arrayname+i)

如果使用的指针,而不是数组名,则C++也将执行同样的转换

pointername[i] becomes *(pointername+i)

因此,在很多情况下,可以相同的方式使用指针名和数组名。对于它们,可以使用数组方括号表示法,也可以使用解除引用运算符(*)。在多数表达式中,它们都表示地址。区别之一是,可以修改指针的值,而数组名是常量:

pointername=pointername+1;		//valid
arrayname=arrayname+1;			//not allow

另一个区别是,对数组应用sizeof运算符得到的是数组的长度,而对指针应用sizeof得到的是指针的长度,即使指针指向的是一个数组。

数组的指针

short tell[10];
cout<<tell;				//displays &tell[0]
cout<<&tell;			//displays address of whole array

​ 从数字上说,两个地址是相同的;但从概念上说,&tell[0](即tell)是一个2字节内存块的地址,而&tell是一个20字节内存块的地址。换句话说,tell是一个short指针(short*),而&tell是一个这样的指针,即指向包含10个元素的short数组(short( * )[10])。

short(*pas)[10]=&tell;

指针小结

  • 声明指针
typeName* pointerName;
double* pn;
char* pc;
  • 给指针赋值

应将内存地址赋给指针。可以对变量名应用 &运算符,来获得被命名的内存的地址,new运算符返回未命名的内存的地址。

double* pn;
double* pa;
char *pc;
double bubble=3.2;pn=&bubble;
pc=new char;
pa=new double[30];
  • 对指针解除引用
cout<< *pn;		//3.2
*pc='s';	

另一种对指针解除引用的方法是使用数组表示法,例如,pn[0]与*pn是一样的。决不要对未被初始化为适当地址的指针解除引用。

  • 区分指针和指针所指向的值
int* pt=new int;	//assigns an address to the pointer pt
*pt=5;				//stores the value 5 at that address
  • 数组名

在多数情况下,C++将数组名视为数组的第1个元素的地址

int tacos[10];
  • 指针算术

C++允许将指针和整数相加。加1的结果等于原来的地址值加上指向的对象占用的总字节数。还可以将一个指针减去另一个指针,获得两个指针的差。

仅当两个指针指向同一个数组(也可以指向超出结尾的一个位置)时,这种运算才有意义。

int tacos[10]={5,2,8,2,3,4,5,5,6,7};
int* pt=tacos;
pt=pt+1;
int* pe=&tacos[9];
pe=pe-1;
int diff=pe-pt;
  • 数组的动态联编和静态联编
//static
int tacos[10];//dynamic
int size;
cin>>size;
int *pz=new int[size];
...
delete[]pz;
  • 数组表示法和指针表示法

使用方括号数组表示法等同于对指针解除引用

tacos[0]
tacos[3]

数组名和指针变量都是如此。因此对于指针和数组名,即可以使用指针表示法,也可以使用数组表示法

int *pt=new int[10];
*pt=5;
pt[0]=6;
pt[9]=44;int coats[10];
*(coats+4)=12;

指针和字符串

注意:

在cout和多数C++表达式中,char数组名、char指针以及用括号扩起来的字符串常量都被解释为字符串第一个字符的地址。

// ptrstr.cpp -- using pointers to strings
#include <iostream>
#include <cstring>              // declare strlen(), strcpy()int main() {using namespace std;char animal[20] = "bear";   // animal holds bearconst char *bird = "wren";  // bird holds address of stringchar *ps;                   // uninitializedcout << animal << " and ";  // display bearcout << bird << "\n";       // display wren// cout << ps << "\n";      //may display garbage, may cause a crashcout << "Enter a kind of animal: ";cin >> animal;              // ok if input < 20 chars// cin >> ps; Too horrible a blunder to try; ps doesn't//            point to allocated spaceps = animal;                // set ps to point to stringcout << ps << "!\n";       // ok, same as using animalcout << "Before using strcpy():\n";cout << animal << " at " << (int *) animal << endl;cout << ps << " at " << (int *) ps << endl;ps = new char[strlen(animal) + 1];  // get new storagestrcpy(ps, animal);         // copy string to new storagecout << "After using strcpy():\n";cout << animal << " at " << (int *) animal << endl;cout << ps << " at " << (int *) ps << endl;delete [] ps;// cin.get();// cin.get();return 0;
}
/*
bear and wren
Enter a kind of animal: fox
fox!
Before using strcpy():
fox at 0x62fdf0
fox at 0x62fdf0
After using strcpy():
fox at 0x62fdf0
fox at 0x2576cd0
*/

通过使用strcpy()和new,将获得"fox"的两个独立副本

经常需要将字符串放到数组中。初始化数组时,请使用=运算符;否则应使用strcpy()或strncpy()。

char food[20]="carrots";		//initalization
strcpy(food,"flan");			//otherwise

对于strncpy()

strncpy(food,"a picnic basket filled with many goodies",19);
food[19]='\0';

这样最多将19个字符复制到数组中,然后将最后一个元素设置成空字符。如果该字符串少于19个字符,则strncpy()将在复制完该字符串之后加上空字符,以 标记该字符串的结尾。

使用new创建动态结构

在这里插入图片描述

提示

如果结构标识符时结构名,则使用句点运算符;如果标识符是指向结构的指针,则使用箭头运算符。

另一种访问结构成员的方法是,如果ps是指向结构的指针,则*ps就是被指向的值——结构本身。由于*ps是一个结构,因此(*ps).price是该结构的price成员。
// newstrct.cpp -- using new with a structure
#include <iostream>struct inflatable { // structure definitionchar name[20];float volume;double price;
};int main() {using namespace std;inflatable *ps = new inflatable;  // allot memory for structurecout << "Enter name of inflatable item: ";cin.get(ps->name, 20);            // method 1 for member accesscout << "Enter volume in cubic feet: ";cin >> (*ps).volume;              // method 2 for member accesscout << "Enter price: $";cin >> ps->price;cout << "Name: " << (*ps).name << endl;              // method 2cout << "Volume: " << ps->volume << " cubic feet\n"; // method 1cout << "Price: $" << ps->price << endl;             // method 1delete ps;                        // free memory used by structure// cin.get();// cin.get();return 0;
}
/*
Enter name of inflatable item: Fab
Enter volume in cubic feet: 1.4
Enter price: $27.99
Name: Fab
Volume: 1.4 cubic feet
Price: $27.99
*/
  • 使用new和delete
// delete.cpp -- using the delete operator
#include <iostream>
#include <cstring>      // or string.h
using namespace std;
char *getname(void);    // function prototypeint main() {char *name;         // create pointer but no storagename = getname();   // assign address of string to namecout << name << " at " << (int *) name << "\n";delete [] name;     // memory freedname = getname();   // reuse freed memorycout << name << " at " << (int *) name << "\n";delete [] name;     // memory freed again// cin.get();// cin.get();return 0;
}char *getname() {       // return pointer to new stringchar temp[80];      // temporary storagecout << "Enter last name: ";cin >> temp;char *pn = new char[strlen(temp) + 1];strcpy(pn, temp);   // copy string into smaller spacereturn pn;          // temp lost when function ends
}/*
Enter last name: Fredlkin
Fredlkin at 0x726cd0
Enter last name: Pook
Pook at 0x726cd0
*/

自动存储、静态存储和动态存储

  • 自动存储

​ 在函数内部定义的常规变量使用自动存储空间,被称为自动变量,这以为着它们在所属的函数被调用时自动产生,在该函数结束时消亡。

​ 实际上,自动变量是一个局部变量,其作用域为包含它的代码块。

​ 自动变量通常存储在栈中。这意味着执行代码块时,其中的变量依次加入到栈中,而离开代码块时,将按相反的顺序释放这些变量。这被称为后进先出(LIFO)。因此,在程序执行的过程中,栈不断地增大和缩小。

  • 静态存储

​ 静态存储是整个程序执行期间都存在的存储方式。使变量称为静态的方式有两种:一种是在函数外面定义它;另一种是在声明变量时使用关键字static:

static double fee=56.50;
  • 动态存储

​ new和delete运算符提供了一种比自动变量和静态变量更灵活的方法。它们管理了一个内存池,这在C++中被称为自由存储空间(free store)或堆(heap)。该内存池同用于静态变量和自动变量的内存时分开的。

​ new和delete让我们能够在一个函数中分配内存,在另一个函数中释放它。因此,数据的生命周期不完全受程序或函数的生存时间控制。

栈、堆和内存泄漏

​ 如果使用了new运算符在自由存储空间(或堆)上创建变量后,没有调用delete,将会发生什么?

​ 如果没有调用delete,则即使包含指针的内存由于作用域规则和对象生命周期的原因而被释放,在自由存储空间上动态分配的变量或结构也将继续存在。实际上,将会无法访问自由存储空间中的结构,因为指向这些内存的指针无效。这将导致内存泄漏。被泄漏的内存将在程序的整个生命周期内都不可使用;这些内存被分配出去,但无法收回。

4.9、类型组合

//结构定义
struct antarctica_year_end
{int year;
};antarctica_year_end s01,s02,s03;		//创建变量
s01.year=1998;							//使用成员运算符访问成员antarctica_year_end=&s02;				//创建指向这种结构的指针
pa->year=1999;							//使用间接成员运算符访问成员antarctica_year_end trio[3];			//创建结构数组
trio[0].year=2003;						//使用成员运算符访问成员
(trio+1)->year=2004;					//使用间接成员运算符const antarctica_year_end* arp[3]={&s01,&s02,&s03};		//创建指针数组
std::cout<<arp[1]->year<<std::endl;						//使用间接运算符const antarctica_year_end** ppa=arp;					//创建上面数组的指针 ppa=arp
std::cout<<(*ppa)->year<<std::endl;					//*ppa为&s01,式子为s01的year成员
std::cout<<(*(ppb+1))->year<<std::endl;

例子

// mixtypes.cpp --some type combinations
#include <iostream>struct antarctica_years_end
{int year;/* some really interesting data, etc. */
};int main()
{antarctica_years_end s01, s02, s03; s01.year = 1998;antarctica_years_end * pa = &s02;pa->year = 1999;antarctica_years_end trio[3]; // array of 3 structurestrio[0].year = 2003;std::cout << trio->year << std::endl;const antarctica_years_end * arp[3] = {&s01, &s02, &s03};std::cout << arp[1]->year << std::endl;const antarctica_years_end ** ppa = arp; auto ppb = arp; // C++0x automatic type deduction
// or else use const antarctica_years_end ** ppb = arp; std::cout << (*ppa)->year << std::endl;std::cout << (*(ppb+1))->year << std::endl;// std::cin.get();return 0;
}
/*
2003
1999
1998
1999
*/

4.10、vector、array

vector

模板类vector类似于string类,也是一种动态数组。可以在运行阶段设置vector对象的长度,可以在末尾附加新数据,还可以再中间插入新数据。

声明创建一个名为vt的vector对象,它可以存储n_elem个类型为typeName的元素

vector<typeName> vt(n_elem)
//其中参数n_elem可以是整型常量,也可以是整型变量。#include<vector>
using namespace std;
vector<int>vi;
int n;
cin>>n;
vector<double> vd(n);

array

​ vector类的功能比数组强大,但代价是效率较低。如果需要长度固定的数组,使用数组是更佳的选择,但代价是不那么方便和安全。array,也位于名称空间std中。

​ 与数组一样,array对象的长度也是固定的,也使用栈(静态内存分配),而不是自由存储区,因此其效率与数组相同,但更方便、安全。

array<typeName,n_elem> arr;
//声明创建一个名为arr的array对象,它包含n_elem个类型为typeName的元素。
//n_elem不能是变量#include<array>
....
using namespace std;
array<int,5> ai;
array<double,4>ad={1.2, 2.1, 3.43, 4.3};

对比

// choices.cpp -- array variations
#include <iostream>
#include <vector>   // STL C++98
#include <array>    // C++0xint main() {using namespace std;
// C, original C++double a1[4] = {1.2, 2.4, 3.6, 4.8};
// C++98 STLvector<double> a2(4);   // create vector with 4 elements
// no simple way to initialize in C98a2[0] = 1.0 / 3.0;a2[1] = 1.0 / 5.0;a2[2] = 1.0 / 7.0;a2[3] = 1.0 / 9.0;
// C++0x -- create and initialize array objectarray<double, 4> a3 = {3.14, 2.72, 1.62, 1.41};array<double, 4> a4;a4 = a3;     // valid for array objects of same size
// use array notationcout << "a1[2]: " << a1[2] << " at " << &a1[2] << endl;cout << "a2[2]: " << a2[2] << " at " << &a2[2] << endl;cout << "a3[2]: " << a3[2] << " at " << &a3[2] << endl;cout << "a4[2]: " << a4[2] << " at " << &a4[2] << endl;
// misdeeda1[-2] = 20.2;cout << "a1[-2]: " << a1[-2] << " at " << &a1[-2] << endl;cout << "a3[2]: " << a3[2] << " at " << &a3[2] << endl;cout << "a4[2]: " << a4[2] << " at " << &a4[2] << endl;//  cin.get();return 0;
}/*
a1[2]: 3.6 at 0x62fdf0
a2[2]: 0.142857 at 0x25b6720
a3[2]: 1.62 at 0x62fdb0
a4[2]: 1.62 at 0x62fd90
a1[-2]: 20.2 at 0x62fdd0
a3[2]: 1.62 at 0x62fdb0
a4[2]: 1.62 at 0x62fd90
*/

首先,无论是数组、vector对象还是array对象,都可以使用标准数组表示法来访问各个元素。

其次,从地址中可知,array对象和数组存储在相同的内存区域(即栈)中,而vector对象存储在另一个区域(自由存储区或堆)中。

第三,可以将一个array对象赋给另一个array对象;对于数组,必须逐个元素复制数据。

数组越界无法禁止。对于vector和array对象,可以禁止,但仍然不安全。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/38197.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

B057-spring增强 依赖注入 AOP 代理模式 创建Bean

目录 AOP概念代理模式引出AOP实现方式xml方式实现注解方式实现 AOP 概念 事务管理&#xff1a;比如可以抽取try catch的重复代码 日志监控&#xff1a;比如业务逻辑前后打印关于当前订单数量的日志&#xff0c;了解业务做了什么 性能监控&#xff1a;比如业务前后打印时间&…

浪潮信息赵帅:多元算力时代 开源开放的OpenBMC成为服务器管理优先解

“多元算力时代下&#xff0c;大规模的异构服务器设备面临多种处理器架构、多种设备协议、不同管理芯片兼容的系统化设计挑战&#xff0c;管理固件也迎来新的变革。开源开放的OpenBMC&#xff0c;以创新的分层解耦软件架构&#xff0c;兼容不同处理器架构、算力平台和管理芯片&…

人流目标跟踪pyqt界面_v5_deepsort

直接上效果图 代码仓库和视频演示b站视频006期&#xff1a; 到此一游7758258的个人空间-到此一游7758258个人主页-哔哩哔哩视频 代码展示&#xff1a; YOLOv5 DeepSORT介绍 YOLOv5 DeepSORT是一个结合了YOLOv5和DeepSORT算法的目标检测与多目标跟踪系统。让我为您详细解释一…

【字典学习+稀疏编码Sparse Encoding】简单介绍与sklearn的实现方式

文章目录 1、字典学习与稀疏编码2、sklearn的实现3、示例 1、字典学习与稀疏编码 简单来说&#xff0c;稀疏编码就是把输入向量&#xff08;信号&#xff09;/ 矩阵&#xff08;图像&#xff09;表示为稀疏的系数向量和一组超完备基向量&#xff08;字典&#xff09;的线性组合…

ASP.NET WEB API通过SugarSql连接MySQL数据库

注意&#xff1a;VS2022企业版可以&#xff0c;社区版可能存在问题。实体名称和字段和数据库中的要一致。 1、创建项目&#xff0c;安装SqlSugarCore、Pomelo.EntityFrameworkCore.MySql插件 2、文件结构 2、appsettings.json { “Logging”: { “LogLevel”: { “Default”: …

搭建WebDAV服务手机ES文件浏览器远程访问

文章目录 1. 安装启用WebDAV2. 安装cpolar3. 配置公网访问地址4. 公网测试连接5. 固定连接公网地址6. 使用固定地址测试连接 有时候我们想通过移动设备访问群晖NAS 中的文件,以满足特殊需求,我们在群辉中开启WebDav服务,结合cpolar内网工具生成的公网地址,通过移动客户端ES文件…

docker通用镜像方法,程序更新时不用重新构建镜像

docker通用镜像方法&#xff0c;程序更新时不用重新构建镜像。更新可执行文件后&#xff0c;重新启动容器就可运行。 功能 1、在demo目录下添加脚本文件start.sh&#xff0c;里面执行demo.jar文件。 2、将demo目录映射到镜像下的 /workspace目录。 3、Dockerfile文件中默认…

台湾shopee:虾皮电商平台选品方法与市场机遇

台湾Shopee虾皮电商平台为台湾本土卖家和消费者提供了一个线上交易平台。对于想要在台湾市场做虾皮电商的卖家来说&#xff0c;选择合适的产品是非常重要的。本文介绍一些做虾皮电商的选品方法和策略。 首先&#xff0c;了解市场需求是选品的基础。在进入台湾Shopee市场之前&a…

【Spring专题】Spring之Bean的生命周期源码解析——阶段二(IOC之实例化)

目录 前言阅读准备阅读指引阅读建议 课程内容一、SpringIOC之实例化1.1 简单回顾1.2 概念回顾1.3 核心方法讲解 二、方法讲解2.1 AbstractBeanFactory#getMergedLocalBeanDefinition&#xff1a;合并BeanDefinition2.2 AbstractAutowireCapableBeanFactory#createBean&#xff…

安达发APS|APS排产软件之计划甘特图

在当今全球化和竞争激烈的市场环境下&#xff0c;制造业企业面临着巨大的压力&#xff0c;如何在保证产品质量、降低成本以及满足客户需求的同时&#xff0c;提高生产效率和竞争力成为企业需要迫切解决的问题。在这个背景下&#xff0c;生产计划的制定和执行显得尤为重要。然而…

2023年京东按摩仪行业数据分析(京东销售数据分析)

近年来&#xff0c;小家电行业凭借功能与颜值&#xff0c;取代黑电和白电&#xff0c;成为家电市场的主要增长点。在这一市场背景下&#xff0c;颜值更高、功能更丰富、品种更齐全的各类按摩仪&#xff0c;借助新消费和电子商务的风潮&#xff0c;陆续被推上市场。今年&#xf…

【Cocos Creator 项目实战 】消灭星星加强版(附带完整源码工程)

本文乃Siliphen原创&#xff0c;转载请注明出处 目录 概述 游戏整体流程 游戏框架设计 单一职责的类 主要流程控制类 核心玩法模块 UI&#xff1a; 游戏世界&#xff1a; 本文项目的代码组织结构 作者项目实践总结 场景只有一个入口脚本 尽量少在节点上挂载脚本 构…

从零构建深度学习推理框架-8 卷积算子实现

其实这一次课还蛮好理解的&#xff1a; 首先将kernel展平&#xff1a; for (uint32_t g 0; g < groups; g) {std::vector<arma::fmat> kernel_matrix_arr(kernel_count_group);arma::fmat kernel_matrix_c(1, row_len * input_c_group);for (uint32_t k 0; k < k…

macOS(m芯片)连接服务器及其进行文件传输的各种方式的详解

说明&#xff1a;使用了macOS后发现&#xff0c;win系统能使用的xshell、xftp等连接服务器及其文件传输等软件均不能使用了&#xff0c;没有兼容的版本。所以我们刚切换到mac系统该如何去适应呢。 一、连接远程服务器 macOS中前文也说道我们使用的是iterm2进行终端控制的&…

基于深度信念神经网络的矿石产量预测,基于DBN的矿石产量预测,DBN的详细原理

目录 背影 DBN神经网络的原理 DBN神经网络的定义 受限玻尔兹曼机(RBM) DBN的矿石产量预测 基本结构 主要参数 数据 MATALB代码 结果图 展望 背影 DBN是一种深度学习神经网络,拥有提取特征,非监督学习的能力,是一种非常好的分类算法,本文将DBN算法进行矿石产量预测 DB…

流量日志分析--实操

[鹤城杯 2021]流量分析 <--第一道流量分析不难,主要就是布尔盲注的流量包分析,直接查看http请求包即可我们可以通过观察看到注入成功的响应长度不同,这里成功的为978字节,失败的994字节.不要问为什么.其实也可以直接判断.978的流量比994的少了非常多 显然就是成功的(因为这里…

Docker中部署redis

1.部署redis要求 2.部署教程 连接容器中的redis redis部署完毕

大模型基础:GPT家族与提示学习

大模型基础:GPT 家族与提示学习 从 GPT-1 到 GPT-3.5 GPT(Generative Pre-trained Transformer)是 Google 于2018年提出的一种基于 Transformer 的预训练语言模型。它标志着自然语言处理领域从 RNN 时代进入 Transformer 时代。GPT 的发展历史和技术特点如下: GPT-12018年6月…

QQ附近人引流的几个详细方法,qq附近人引流脚本实操演示教程

大家好我是你们的小编一辞脚本&#xff0c;今天给大家分享新的知识&#xff0c;很开心可以在CSDN平台分享知识给大家,很多伙伴看不到代码我先录制一下视频 在给大家做代码&#xff0c;给大家分享一下qq引流脚本的知识和视频演示 不懂的小伙伴可以认真看一下&#xff0c;我们一…

【CSS】CSS 布局——常规流布局

<h1>基础文档流</h1><p>我是一个基本的块级元素。我的相邻块级元素在我的下方另起一行。</p><p>默认情况下&#xff0c;我们会占据父元素 100%的宽度&#xff0c;并且我们的高度与我们的子元素内容一样高。我们的总宽度和高度是我们的内容 内边距…