new_delete_sizeof

#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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值