创建和使用数组
创建和使用C-风格字符串
创建和使用string类字符串
使用方法getline()和get()读取字符串
混合输入字符串和数字
创建和使用结构
创建和使用共用体
创建和使用枚举
创建和使用指针
使用new和delete管理动态内存
创建动态数组
创建动态结构
自动存储、静态存储和动态存储
vector和array类简介
目录
4.1 数组
存储在每个元素中的值的类型
数组名
数组中的元素数
4.1.1 程序说明
// arrayone.cpp -- small arrays of integers
#include <iostream>
int main()
{
using namespace std;
int yams[3]; // creates array with three elements
yams[0] = 7; // assign value to first element
yams[1] = 8;
yams[2] = 6;
int yamcosts[3] = {20, 30, 5}; // create, initialize array
// NOTE: If your C++ compiler or translator can't initialize
// this array, use static int yamcosts[3] instead of
// int yamcosts[3]
cout << "Total yams = ";
cout << yams[0] + yams[1] + yams[2] << endl;
cout << "The package with " << yams[1] << " yams costs ";
cout << yamcosts[1] << " cents per yam.\n";
int total = yams[0] * yamcosts[0] + yams[1] * yamcosts[1];
total = total + yams[2] * yamcosts[2];
cout << "The total yam expense is " << total << " cents.\n";
cout << "\nSize of yams array = " << sizeof yams;
cout << " bytes.\n";
cout << "Size of one element = " << sizeof yams[0];
cout << " bytes.\n";
// cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
Total yams = 21
The package with 8 yams costs 30 cents per yam.
The total yam expense is 410 cents.
Size of yams array = 12 bytes.
Size of one element = 4 bytes.
4.1.2 数组的初始化规则
4.1.3 C++11数组初始化方法
新增:
1.初始化数组,省略=
double earnings[4] {1,2,3,4}
2.大括号不写值,默认设置为0
float balance[100] {};
3.列表初始化禁止缩窄转换
long plies[] = {25, 92, 3.0}; 错误
char splits[4] {'h', 'I', 1122011, '\0'} 错误
char tiles[4] {'h', 'I', 112, '\0'} 正确
浮点数转化为整型为缩窄操作,即使小数点为0
超出char变量的取值范围
4.2 字符串
C++处理字符串的方式
(1)C-style string
(2)string类库
C-style string
空字符很重要!!
因为饿不应将不是字符串的字符数组当作字符串来处理
char dog[8] = {'b','e','a','u','X','','I','I'}; // not a string
char cat[8] = {'b','e','a','u','X','','I','\0'}; //a string
用双引号括起的字符串隐式地包括结尾的空字符,称为字符串常量,字符串字面值‘
char bird[11] = "Mr. Cheeps";
char fish[] = "Bubbles";
C++输入工具通过键盘输入,将字符串读入到char数组中时,将自动加上结尾的空字符
char a = 'S';//字符常量
“F”='F' + \0
“F”实际表示字符串所在的内存地址
char b = "F";//字符串常量
4.2.1 拼接字符串常量
C++允许将两个用引号括起来的字符串合并成一个
4.2.2 在数组中使用字符串
// strings.cpp -- storing strings in an array
#include <iostream>
#include <cstring> // for the strlen() function
int main()
{
using namespace std;
const int Size = 15;
char name1[Size]; // empty array
char name2[Size] = "C++owboy"; // initialized array
// NOTE: some implementations may require the static keyword
// to initialize the array name2
cout << "Howdy! I'm " << name2;
cout << "! What's your name?\n";
cin >> name1;
cout << "Well, " << name1 << ", your name has ";
cout << strlen(name1) << " letters and is stored\n";
cout << "in an array of " << sizeof(name1) << " bytes.\n";
cout << "Your initial is " << name1[0] << ".\n";
name2[3] = '\0'; // set to null character
cout << "Here are the first 3 characters of my name: ";
cout << name2 << endl;
// cin.get();
// cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ strings.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
Howdy! I'm C++owboy! What's your name?
Basiman
Well, Basiman, your name has 7 letters and is stored
in an array of 15 bytes.
Your initial is B.
Here are the first 3 characters of my name: C++
sizeof运算符指出整个数组的长度
strlen()函数返回存储在数组中的字符串的长度
4.2.3 字符串输入
// instr1.cpp -- reading more than one string
#include <iostream>
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin >> name;
cout << "Enter your favorite dessert:\n";
cin >> dessert;
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
// cin.get();
// cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ instr1.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
Enter your name:
Alistair Drreeb
Enter your favorite dessert:
I have some delicious Drreeb for you, Alistair.
cin使用空白(空格、制表符和换行符)来确定字符串的结束位置
4.2.4 每次读取一行字符串输入
面向行而不是面向单词的方法
istream中的类提供了一些面向行的类成员函数:getline()和get()。
这两个函数读读取一行输入,直到达到换行符。
随后getline()丢弃换行符,而get()将换行符保留在输入序列中
// instr2.cpp -- reading more than one word with getline
#include <iostream>
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin.getline(name, ArSize); // reads through newline
cout << "Enter your favorite dessert:\n";
cin.getline(dessert, ArSize);
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
// cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
Enter your name:
Dirk Hammernose
Enter your favorite dessert:
Raadish Torte
I have some delicious Raadish Torte for you, Dirk Hammernose.
// instr3.cpp -- reading more than one word with get() & get()
#include <iostream>
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin.get(name, ArSize).get(); // read string, newline
cout << "Enter your favorite dessert:\n";
cin.get(dessert, ArSize).get();
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
// cin.get();
return 0;
}
wlsh@wlsh-MacbookPro] chapter_4$ g++ instr3.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
Enter your name:
Mai Parfait
Enter your favorite dessert:
Chocolate Mousse
I have some delicious Chocolate Mousse for you, Mai Parfait.
get()不再读取并丢弃换行符,而是将其留在输入队列中。
cin.get(name,ArSize);
换行符留在输入队列中。
cin.get(dessert.Artsize);
看到第一个字符是换行符,认为get()到达行尾,没有发现任何可读取的内容。
解决方法如上,两个类成员函数拼接
4.2.5 混合输入字符串和数字
// numstr.cpp -- following number input with line input
#include <iostream>
int main()
{
using namespace std;
cout << "What year was your house built?\n";
int year;
cin >> year;
// cin.get();
//( cin >> year).get();
cout << "What is its street address?\n";
char address[80];
cin.getline(address, 80);
cout << "Year built: " << year << endl;
cout << "Address: " << address << endl;
cout << "Done!\n";
// cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ numstr.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
What year was your house built?
1966
What is its street address?
Year built: 1966
Address:
Done!
cin,将回车键生成的换行符留在输入队列中,
后面的get.line()看到换行符后,认为是一个空行,将空字符串赋值给address数组
解决方法,读取地址之前丢弃换行符
cin.get()
4.3 string类简介
string类,头文件string。
位于名称空间std中。
隐藏了字符串的数组性质,处理普通变量那样处理字符串。
与字符数组的区别是,
(1)string对象声明为简单变量,而不是数组。
(2)因为类设计让程序自动处理string的大小
C-风格初始化string对象
cin将键盘输入到string对象
cout显示string对象
数组表示法
// strtype1.cpp -- using the C++ string class
#include <iostream>
#include <string> // make string class available
int main()
{
using namespace std;
char charr1[20]; // create an empty array
char charr2[20] = "jaguar"; // create an initialized array
string str1; // create an empty string object
string str2 = "panther"; // create an initialized string
cout << "Enter a kind of feline: ";
cin >> charr1;
cout << "Enter another kind of feline: ";
cin >> str1; // use cin for input
cout << "Here are some felines:\n";
cout << charr1 << " " << charr2 << " "
<< str1 << " " << str2 // use cout for output
<< endl;
cout << "The third letter in " << charr2 << " is "
<< charr2[2] << endl;
cout << "The third letter in " << str2 << " is "
<< str2[2] << endl; // use array notation
// cin.get();
// cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ strtype1.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
Enter a kind of feline: ocelot
Enter another kind of feline: tiger
Here are some felines:
ocelot jaguar tiger panther
The third letter in jaguar is g
The third letter in panther is n
4.3.1 C++11字符串初始化
4.3.2 辅助、拼接和附加
合并:str1 += str2
// strtype2.cpp �- assigning, adding, and appending
#include <iostream>
#include <string> // make string class available
int main()
{
using namespace std;
string s1 = "penguin";
string s2, s3;
cout << "You can assign one string object to another: s2 = s1\n";
s2 = s1;
cout << "s1: " << s1 << ", s2: " << s2 << endl;
cout << "You can assign a C-style string to a string object.\n";
cout << "s2 = \"buzzard\"\n";
s2 = "buzzard";
cout << "s2: " << s2 << endl;
cout << "You can concatenate strings: s3 = s1 + s2\n";
s3 = s1 + s2;
cout << "s3: " << s3 << endl;
cout << "You can append strings.\n";
s1 += s2;
cout <<"s1 += s2 yields s1 = " << s1 << endl;
s2 += " for a day";
cout <<"s2 += \" for a day\" yields s2 = " << s2 << endl;
//cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ strtype2.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
You can assign one string object to another: s2 = s1
s1: penguin, s2: penguin
You can assign a C-style string to a string object.
s2 = "buzzard"
s2: buzzard
You can concatenate strings: s3 = s1 + s2
s3: penguinbuzzard
You can append strings.
s1 += s2 yields s1 = penguinbuzzard
s2 += " for a day" yields s2 = buzzard for a day
4.3.3 string类的其他操作
string对象的技术 和 用于字符数组的技术进行比较
头文件cstring(string.h)提供函数,程序员可以使用C语言库中的函数完成任务
// strtype3.cpp -- more string class features
#include <iostream>
#include <string> // make string class available
#include <cstring> // C-style string library
int main()
{
using namespace std;
char charr1[20];
char charr2[20] = "jaguar";
string str1;
string str2 = "panther";
// assignment for string objects and character arrays
str1 = str2; // copy str2 to str1
strcpy(charr1, charr2); // copy charr2 to charr1
//string具有自动调节大小的功能,
// appending for string objects and character arrays
str1 += " paste"; // add paste to end of str1
strcat(charr1, " juice"); // add juice to end of charr1
// finding the length of a string object and a C-style string
int len1 = str1.size(); // obtain length of str1
//str1是一个string对象,而size()是string类的方法
int len2 = strlen(charr1); // obtain length of charr1
//接受C-风格字符串作为参数
cout << "The string " << str1 << " contains "
<< len1 << " characters.\n";
cout << "The string " << charr1 << " contains "
<< len2 << " characters.\n";
// cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ strtype3.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
The string panther paste contains 13 characters.
The string jaguar juice contains 12 characters.
strcat() 和 strlcpy() 指出目标数组最大允许长度的第三个参数
4.3.4 string类I/O
// strtype4.cpp -- line input
#include <iostream>
#include <string> // make string class available
#include <cstring> // C-style string library
int main()
{
using namespace std;
char charr[20];
string str;
cout << "Length of string in charr before input: "
<< strlen(charr) << endl;
cout << "Length of string in str before input: "
<< str.size() << endl;
cout << "Enter a line of text:\n";
cin.getline(charr, 20); // indicate maximum length
cout << "You entered: " << charr << endl;
cout << "Enter another line of text:\n";
getline(cin, str); // cin now an argument; no length specifier
cout << "You entered: " << str << endl;
cout << "Length of string in charr after input: "
<< strlen(charr) << endl;
cout << "Length of string in str after input: "
<< str.size() << endl;
// cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ strtype4.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
Length of string in charr before input: 0
Length of string in str before input: 0 //未被初始化的string类对象自动设置为0
Enter a line of text:
peanut butter
You entered: peanut butter
Enter another line of text:
blueberry jam
You entered: blueberry jam
Length of string in charr after input: 13
Length of string in str after input: 13
cin.getline(charr,20);
cin是一个istream对象,函数etline()是istream类的类方法
getline(cin,str);
将cin作为参数,指出到哪里去查找输入。也没有指出到哪里去找查找输入,因为string对象根据字符串的长度自动调整大小
4.3.5 其他形式的字符串字面值
P88需要再看
4.4 结构简介
比数组更灵活的数据格式
4.4.1 在程序中使用结构
// 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 value
1.88, // volume value
29.99 // price value
}; // guest is a structure variable of type inflatable
// It's initialized to the indicated values
inflatable 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 variable
cout << "You can have both for $";
cout << guest.price + pal.price << "!\n";
// cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ structur.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
Expand your guest list with Glorious Gloria and Audacious Arthur!
You can have both for $62.98!
4.4.2 C++11结构初始化
支持列表初始化用于结构
=可选
inflatable duck {"Daphe", 0.12, 9.98};
inflatable duck {};
4.4.3 结构可以将string类作为成员吗
可以
std:string name;
4.4.4 其他结构属性
// 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 another
cout << "choice: " << choice.name << " for $";
cout << choice.price << endl;
// cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ assgn_st.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
bouquet: sunflowers for $12.49
choice: sunflowers for $12.49
到目前为止讨论的都能用在C结构中,
C++结构除了成员变量外,还有成员函数,通常用于类中。
4.4.5 结构数组
// 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;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ arrstruct.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
The guests Bambi and Godzilla
have a combined volume of 2000.5 cubic feet.
4.4.6 结构中的位字段
指定使用的位数
struct toggle_register
{
unsigned int SN : 4;
unsigned int : 4;
bool goodIn : 1;
bool goodTorgle : 1;
}
4.5 共用体
只能同时存储一种类型,只能存储int、long、double。
共用体的用途之一是,当数据项使用两种或更多格式时,可节省空间。
union {
}
4.6 枚举
C++的enum工具提供了另一种创建符号常量的方式,代替const,允许定义新类型。
enum spectrum {red, orange, yellow, green, blue, violet, indigo, ultraviolet};
spectrum为新类型的名称,枚举(enumeration)
符号常量,对应整数0~7 枚举量(enumerator)
spectrum band;
band = blue;
band = blue + 3;错误 blue converted to int
band = spectrum(3);
4.6.1 设置枚举量的值
enum spectrum {red, orange=1, yellow=4, green, blue, violet, indigo, ultraviolet};
4.6.2 枚举的取值范围
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;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ address.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
donuts value = 6 and donuts address = 0x7ffee08a99d8
cups value = 4.5 and cups address = 0x7ffee08a99d0
先存储cups,再存储donuts
使用常规变量时,值是指定的值,而地址为派生量。
处理存储的策略相反,地址是指定的值,而值为派生量。
指针名表示的是地址
*运算符 为 间接值(indirect velue)或解除饮用(dereferencing)
应用在指针,可以得到该地址出存储的值
#include <iostream>
int main()
{
using namespace std;
int updates = 6; // declare a variable
int * p_updates; // declare pointer to an int
p_updates = &updates; // assign address of int to pointer
// express values two ways
cout << "Values: updates = " << updates;
cout << ", *p_updates = " << *p_updates << endl;
// express address two ways
cout << "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 = 0x7ffeefbff528, p_updates = 0x7ffeefbff528
Now updates = 7
4.7.1 声明和初始化指针
int* a; //a pointer to type int
int*是一种类型--指向int的指针
char的地址与double的地址长度相同,
这取决于计算机系统
// 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;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ init_ptr.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
Value of higgens = 5; Address of higgens = 0x7ffee71dc9d8
Value of *pt = 5; Value of pt = 0x7ffee71dc9d8
4.7.2 指针的危险
C++中的创建指针时,计算机将分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存。
4.7.3 指针和数字
int* pt;
pt = 0xB8000000; //type mismatch
pt = (int*) 0xB8000000; //types now match
4.7.4 使用new来分配内存
// 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 there
cout << "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 there
cout << "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;
}
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
nights value = 1001: location 0x7ffee2d109d8
int value = 1001: location = 0x7f9aabc02aa0
double value = 1e+07: location = 0x7f9aabc02ab0
location of pointer pd: 0x7ffee2d109c8
size of pt = 8: size of *pt = 4
size of pd = 8: size of *pd = 8
C库函数malloc()分配内存
C++:new运算符‘
new运算符根据类型确定需要多少字节的内存。
在程序运行时进行的。
常规变量的值存储在被称为栈(stack)的内存区域中
new从堆(heap)或自由存储区(free sotre)的内存区域分配内存。
4.7.5 使用delete释放内存
C++内存管理数据包的一个方面
int* a = new int;
..
delete a;
释放a指向的内存,但不会删除指针a本身,可以将a重新指向另一个新分配的内存快。
警告:只能用delete来释放用new分配的内存,
int a = 5;
int* b = &a;
delete b; 错误
4.7.6 使用new来创建动态数组
静态联编(static binding):在编译时给数组分配内存
动态联编(dynamic binding):数组在运行时创建。动态数组
int* psome = new int [10];
delete [] some;
指向第一个元素
// arraynew.cpp -- using the new operator for arrays
#include <iostream>
int main()
{
using namespace std;
double * p3 = new double [3]; // space for 3 doubles
p3[0] = 0.2; // treat p3 like an array name
p3[1] = 0.5;
p3[2] = 0.8;
cout << "p3[1] is " << p3[1] << ".\n";
p3 = p3 + 1; // increment the pointer
cout << "Now p3[0] is " << p3[0] << " and ";
cout << "p3[1] is " << p3[1] << ".\n";
p3 = p3 - 1; // point back to beginning
delete [] p3; // free the memory
// cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ arraynew.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
p3[1] is 0.5.
Now p3[0] is 0.5 and p3[1] is 0.8.
C和C++内部使用指针来处理数组。数组和指针等价时C和C+的优点
将指针当作数组名来使用
C++将数组名解析为地址
4.8 指针、数组和指针算术
// 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 array
double * pw = wages; // name of an array = address
short * ps = &stacks[0]; // or use address operator
// with array element
cout << "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;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ addpntrs.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
pw = 0x7ffee46ab9c0, *pw = 10000
add 1 to the pw pointer:
pw = 0x7ffee46ab9c8, *pw = 20000
ps = 0x7ffee46ab9b6, *ps = 3
add 1 to the ps pointer:
ps = 0x7ffee46ab9b8, *ps = 2
access 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
使用sizeof运算符,这种情况。C++不会将数组名解释为地址
4.8.1 程序说明
注意:将指针变量加1后,其增加的值等于指向的类型占用的字节数。
stack[1] = *(stack + 1);
4.8.2 指针小结
4.8.3 指针和字符串
// ptrstr.cpp -- using pointers to strings
#include <iostream>
#include <cstring> // declare strlen(), strcpy()
int main()
{
using namespace std;
char animal[20] = "bear"; // animal holds bear
const char * bird = "wren"; // bird holds address of string
char * ps; // uninitialized
cout << animal << " and "; // display bear
cout << bird << "\n"; // display wren
// cout << ps << "\n"; //may display garbage, may cause a crash
cout << "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 space
ps = animal; // set ps to point to string
cout << ps << "!\n"; // ok, same as using animal
cout << "Before using strcpy():\n";
cout << animal << " at " << (int *) animal << endl;
cout << ps << " at " << (int *) ps << endl;
ps = new char[strlen(animal) + 1]; // get new storage
strcpy(ps, animal); // copy string to new storage
cout << "After using strcpy():\n";
cout << animal << " at " << (int *) animal << endl;
cout << ps << " at " << (int *) ps << endl;
delete [] ps;
// cin.get();
// cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ ptrstr.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
bear and wren
Enter a kind of animal: fox
fox!
Before using strcpy():
fox at 0x7ffee48599c0
fox at 0x7ffee48599c0
After using strcpy():
fox at 0x7ffee48599c0
fox at 0x7fe242500000
4.8.4 使用new创建动态结构
// newstrct.cpp -- using new with a structure
#include <iostream>
struct inflatable // structure definition
{
char name[20];
float volume;
double price;
};
int main()
{
using namespace std;
inflatable * ps = new inflatable; // allot memory for structure
cout << "Enter name of inflatable item: ";
cin.get(ps->name, 20); // method 1 for member access
cout << "Enter volume in cubic feet: ";
cin >> (*ps).volume; // method 2 for member access
cout << "Enter price: $";
cin >> ps->price;
cout << "Name: " << (*ps).name << endl; // method 2
cout << "Volume: " << ps->volume << " cubic feet\n"; // method 1
cout << "Price: $" << ps->price << endl; // method 1
delete ps; // free memory used by structure
// cin.get();
// cin.get();
return 0;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ newstrct.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
Enter name of inflatable item: Fabulous Frodo
Enter volume in cubic feet: 1.4
Enter price: $27.99
Name: Fabulous Frodo
Volume: 1.4 cubic feet
Price: $27.99
// delete.cpp -- using the delete operator
#include <iostream>
#include <cstring> // or string.h
using namespace std;
char * getname(void); // function prototype
int main()
{
char * name; // create pointer but no storage
name = getname(); // assign address of string to name
cout << name << " at " << (int *) name << "\n";
delete [] name; // memory freed
name = getname(); // reuse freed memory
cout << name << " at " << (int *) name << "\n";
delete [] name; // memory freed again
// cin.get();
// cin.get();
return 0;
}
char * getname() // return pointer to new string
{
char temp[80]; // temporary storage
cout << "Enter last name: ";
cin >> temp;
char * pn = new char[strlen(temp) + 1];
strcpy(pn, temp); // copy string into smaller space
return pn; // temp lost when function ends
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ delete.cpp
[wlsh@wlsh-MacbookPro] chapter_4$ ./a.out
Enter last name: Fredeldumpkin
Fredeldumpkin at 0x7fa64ed00000
Enter last name: Pook
Pook at 0x7fa64ed00000
4.8.5 自动存储、静态存储和动态存储
根据分配内存的方法, C++有3种管理数据内存的方式
4.9 类型组合
// 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 structures
trio[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;
}
[wlsh@wlsh-MacbookPro] chapter_4$ g++ mixtypes.cpp
mixtypes.cpp:22:5: warning: 'auto' type specifier is a C++11 extension [-Wc++11-extensions]
auto ppb = arp; // C++0x automatic type deduction
^
1 warning generated.
4.10 数组的替代品
4.10.1 模版类vector
要使用vector对象,必须包含头文件vector,位于命名空间std种
是使用new创建动态数组的替代品
#include <vector>
using namespace std;
vector <in> vi;
vector<double> vd(n); //create an array of n double.
4.10.2 模版类array(C++11)
vector类的功能强大,但付出的代价效率低。
需要固定长度的数组,使用数组是更佳的选择,array对象长度固定,使用栈(静态内存分配),而不是自由存储区
#include <array>
using namespace std;
array <int, 5> a; //create array object of 5 ints;
array <double, 4> ad = {1.2 ,2.3, 2.4, 2.5}
4.10.3 比较数组、vector对象和array对象
// choices.cpp -- array variations
#include <iostream>
#include <vector> // STL C++98
#include <array> // C++0x
int main()
{
using namespace std;
// C, original C++
double a1[4] = {1.2, 2.4, 3.6, 4.8};
// C++98 STL
vector<double> a2(4); // create vector with 4 elements
// no simple way to initialize in C98
a2[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 object
array<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 notation
cout << "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;
// misdeed
a1[-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;
}
4.11 总结