C++入门(6):复杂的数据类型
内存中,变量类型是根据它们的自然边界进行对齐的;比如,int的起始地址必须是sizeof(int)的整数倍。
std::string s = "asdfgh" ;
std::cout << reinterpret_cast<unsigned long>(&s) << std::endl; //使用C++的显式转换把地址转成十进制输出
int a = 2;
float b = 3.14;
char c = 'A';
double d = 3.1415;
//地址分配从高到低
std::cout << (unsigned long)&a << std::endl; //十进制输出
std::cout << (unsigned long)&b << std::endl;
std::cout << (unsigned long)&c << std::endl;
std::cout << (unsigned long)&d << std::endl;
int numbers[] = {2,3,4,5};
std::cout << (unsigned long)(numbers) << std::endl; //输出 numbers 或者 &numbers 或者 &numbers[0] 都是数组的首地址
运行结果为:
2293396 //string对象s的地址
2293392 //int型占4个字节,分配的地址从上一地址减4,又刚好是4的整数倍
2293388
2293387 //char型占1个字节
2293376 //double型占8个字节,上一地址减8不能被8整除,所以给变量d分配的地址是上一地址减3再减8之后的地址值,此时为8的整数倍
2293360
C++新增了4个强制转换操作符:
static_cast、reinterpret_cast、const_cast和dynamic_cast;
用法:operator<type>(data)
举例:static_cast<float>(2); //即为把2转换成float型的数据
static_cast: 和老式的C强制转换操作符类似;
reinterpret_cast: 可以在不改变实际数据的情况下改变数据类型;
const_cast: 把一个const类型的常量转换为一个非常量值,(还可以把volatile类型的值转换为非volatile值);
dynamic_cast: 要与类搭配使用,可以自动检测转换是否合法。
此外还有一些其他数据类型和C中类似:
struct:结构体;
union: 联合体,每次只能存储这些值中的某一个;
typedef: 给类型创建别名;
enum : 枚举,用来创建一个可取值列表,例如,enum weekdays{Mon,Tue,Wed,Thu,Fri};
枚举值不是字符串,默认是 0–(n-1),n为可取值的个数,此处即为0,1,2,3,4;
当这样定义时:enum weekdays{Mon=2,Tue,Wed=6,Thu,Fri}; 则为2,3,6,7,8。
最后介绍一下C++中的引用数据类型,引用相当于给相关联的变量取别名,任何对引用的操作都是对与其相关联的变量的操作;下面通过以“引用传递”方式向函数传递参数了解有关引用的操作。
void ChangeVal(int &myVal, int newValue) //函数形参是一个引用
{
myVal = newValue; //引用传递,直接使用名字
}
void ChangeVal(int *myVal, int newValue) //函数形参是一个指针,函数重载
{
*myVal = newValue; //使用解引用操作符
}
int& maxTest1(int a, int b) //函数返回值为"引用传递"
{
int &c = a>b?a:b; //引用在定义时就必须初始化
return c;
}
int maxTest2(int a, int b) // 函数返回值为“值传递 ”
{
int c = a>b?a:b;
return c;
}
int main(int argc, char** argv) { //不允许在main函数内部定义函数
int aa = 7;
int &a1 = a; //a1是aa的引用,对a1的任何操作就相当于对aa的操作
std::cout << a1 << '\t' << a << std::endl;
a1 = 2;
std::cout << a1 << '\t' << a << std::endl;
int myValue = 20;
int newValue1 = 70;
int newValue2 = 80;
ChangeVal(myValue,newValue1) ; //传入的是引用,即相当于&myVal = myValue
std::cout << myValue << std::endl;
ChangeVal(&myValue,newValue2) ; //传入的是地址,即相当于*myVal = &myValue
std::cout << myValue << std::endl;
int a = 2;
int b = 5;
int &a1 = a; //a1为指向a的引用
int &c = maxTest1(a,b);
a1 = maxTest1(a,b);
int d;
d = maxTest2(7,9) ;
std::cout << c << std::endl;
std::cout << a1 << '\t' << a << std::endl;
std::cout << d << std::endl;
运行结果为:
7 7
2 2 //a1和aa一起改变
70 //操作引用和操作地址都可以达到预期的改变数值的目的
80
5
5 5 //改变a的引用的值之后,a也改变了
9
以“引用传递”方式向函数传递参数,除了可以改变有关变量的值,“引用传递”方式的另一个好处是它的开销相对要小一些:因为不需要在函数里创建临时变量来容纳那些值,程序的内存占用量自然会小一些。