#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <cctype>
#include <bitset>
using namespace std;
/*
编写程序定义一个 vector 对象,其每个元素都是指向string 类型的指针,读取该 vector 对象,输出每个
string 的内容及其相应的长度
*/
void test_5_1_8(){
string temp;
vector<string*> vec;
while( true ){
cout << "请输入一个字符串:";
cin >> temp;
if( temp.empty() ){
continue;
}
if( temp == "0" ){
break;
}
string *ps = new string;
*ps = temp;
vec.push_back(ps);
}
for( vector<string*>::iterator it = vec.begin(); it != vec.end(); ++it ){
cout << "内容: " << **it << ", 长度: " << (**it).size() << endl;
}
// 释放内存
for( vector<string*>::iterator it = vec.begin(); it != vec.end(); ++it ){
delete *it;
}
}
/*
sizeof 操作符的作用是返回一个对象或类型名的长度,返回值的类型为size_t,长度的单位是字节.
三种用法:
sizeof (type name);
sizeof (expr);
sizeof expr;
1) 对 char 类型或值为 char 类型的表达式做 sizeof 操作保证得 1;
2) 对引用类型做 sizeof 操作将返回存放此引用类型对象所需的内在空间大小;
3) 对指针做 sizeof 操作将返回存放指针所需的内在大小;
4) 注意,如果要获取该指针所指向对象的大小,则必须对指针进行引用。
5) 对数组做 sizeof 操作等效于将对其元素类型做 sizeof 操作的结果乘上数组元素的个数。
因为 sizeof 返回整个数组在内存中的存储长度,所以用 sizeof 数组的结
果除以 sizeof 其元素类型的结果,即可求出数组元素的个数
*/
void test_sizeof(){
int i = 1, j =10000;
cout << sizeof(i) << endl; //4
cout << sizeof(j) << endl; //4
double d = 3.2352;
cout << sizeof(d) << endl; //8
string s1("acaca");
cout << sizeof(s1) << endl; //4
string s2("aavcasevwEFCEWcwfvcwegvcaca");
cout << sizeof(s2) << endl; //4
cout << sizeof(string) << endl; //4
cout << sizeof s2 << endl; //4
string *ps = new string;
cout << sizeof ps << endl; //4
}
void test_array_sizeof(){
int *parray = new int[3];
int i = 0;
for( int *p_begin = parray, *p_end = p_begin+3; p_begin != p_end; ++p_begin ){
*p_begin = i;
++i;
}
// 指针变量parray所占的内存空间大小:4,因为指针变量的值在内存是以16进制的整形保存的,长度为4
cout << sizeof(parray) << endl;
// 第一个数组元素的长度
cout << sizeof(*parray) << endl; //4
delete [] parray;
// 求出数组的长度:
int array[] = {1,2,3};
cout << "数组内存大小为:" << sizeof(array) << endl; //12
cout << "数组的长度为:" << sizeof(array) / sizeof(int) << endl; //3
}
/*
如果不提供显式初始化,动态创建的对象与在函数内定义的变量初始化方式相同。
对于类类型的对象,用该类的默认构造函数初始化;而内置类型的对象则无初始化。
1. 删除( delete )指向动态分配内存的指针失败,因而无法将该
块内存返还给自由存储区。删除动态分配内存失败称为“内存泄
漏(memory leak)”。内存泄漏很难发现,一般需等应用程序运
行了一段时间后,耗尽了所有内存空间时,内存泄漏才会显露出
来。
2. 读写已删除的对象。如果删除指针所指向的对象之后,将指针置
为 0 值,则比较容易检测出这类错误。
3. 对同一个内存空间使用两次 delete 表达式。当两个指针指向同
一个动态创建的对象,删除时就会发生错误。如果在其中一个指
针上做 delete 运算,将该对象的内存空间返还给自由存储区,
然后接着 delete 第二个指针,此时则自由存储区可能会被破坏。
*/
void test_new(){
// 动态创建对象只能用指针表示
// int i = new int; // 错误
int *i = new int;
int *j = new int(10);
int *k = new int(); // 初始化为0
cout << *i << endl; // 没有初始化:7018416
cout << *j << endl; // 10
cout << *k << endl; // 0
string *s1 = new string; // 初始化为空的字符串
string *s2 = new string(5, 'a'); // 初始化为:aaaaa
string *s3 = new string(); // 初始化为空的字符串
cout << *s1 << endl;
cout << *s2 << endl;
cout << *s3 << endl;
// 注意:使用new type()与new type的区别
}
/*
因为前置操作需要做的工作更少,只需加 1 后返
回加 1 后的结果即可。而后置操作符则必须先保存操作数原来的值,以
便返回未加 1 之前的值作为操作的结果。对于 int 型对象和指针,编
译器可优化掉这项额外工作。但是对于更多的复杂迭代器类型,这种额
外工作可能会花费更大的代价。
*/
void test_auto_convert(){
/*
int i; double d;
d = i = 3.5;
cout << i << endl; //3
cout << d << endl; //3
i = d = 3.5;
cout << i << endl; //3
cout << d << endl; //3.5
// 非const对象转换成const对象
int ii = 1;
const int jj = ii;
cout << jj << endl;
*/
/*
将 istream 类型转换为
bool 类型意味着要检验流的状态。如果最后一次读 cin 的尝试是成功的,则流
的状态将导致上述类型转换为 bool 类型后获得 true 值——while 循环条件
成立。如果最后一次尝试失败,比如说已经读到文件尾了,此时将 istream 类
型转换为 bool 类型后得 false,while 循环条件不成立。
*/
string s ;
while( cin >> s ){
// ...
cout << s << endl;
}
}
// 测试强制类型转换
// 强制类型转换操作符:static_cast、dynamic_cast、const_cast 和 reinterpret_cast
// 强制转换的使用场景:
// 1)要覆盖通常的标准转换,所以需显式使用强制类型转换
// 2)可能存在多种转换时,需要选择一种特定的类型转换。
// 注意:强制类型转换是非常危险的
void test_cast(){
// 自动类型转换:
double dval = 3.14;
int ival = 2 ;
ival *= dval;
cout << ival << endl;
// 强制类型转换:
ival *= static_cast<int>(dval);
cout << ival << endl;
/*
命名的强制类型转换符号的一般形式如下:
cast-name<type>(expression);
其中 cast-name 为 static_cast、dynamic_cast、const_cast 和reinterpret_cast 之一,
type 为转换的目标类型,而 expression 则是被强制转换的值。强制转换的类型指定了在 expression
上执行某种特定类型的转换。
dynamic_cast:
dynamic_cast 支持运行时识别指针或引用所指向的对象
const_cast:
const_cast ,顾名思义,将转换掉表达式的 const 性质
static_cast
编译器隐式执行的任何类型转换都可以由 static_cast 显式完成
对于从一个较大的算术类型到一个较小类型的赋值,编译器通常会产
生警告。当我们显式地提供强制类型转换时,警告信息就会被关闭。
可通过 static_cast 将存放在 void* 中的指针值强制转换为原来的指针
类型,此时我们应确保保持指针值。也就是说,强制转换的结果应与原来的地址
值相等。
void* p = &d;
double *dp = static_cast<double*>(p);
reinterpret_cast
reinterpret_cast 通常为操作数的位模式提供较低层次的重新解释
reinterpret_cast 本质上依赖于机器。为了安全地使用
reinterpret_cast,要求程序员完全理解所涉及的数据类型,
以及编译器实现强制类型转换的细节
旧式强制类型转换【不推荐使用】:
type (expr); // Function-style cast notation
(type) expr; // C-language-style cast notation
旧式强制转换依赖于所涉及的数据类型,具有与 const_cast、 static_cast
和 reinterpret_cast 一样的行为。在合法使用 static_cast 或 const_cast
的地方,旧式强制转换提供了与各自对应的命名强制转换一样的功能。如果这两
种强制转换均不合法,则旧式强制转换执行 reinterpret_cast 功能
*/
}
int main() {
test_cast();
return 0;
}
new_delete_sizeof
最新推荐文章于 2022-03-23 13:52:59 发布