遇到的问题

遇到的问题

这个文章用于记录在学习和使用C++的时候遇到的一些问题,以及解决方法,记载了一些非常零散的知识点,没有主题。

new申请结构体,并初始化结构体中的数组

C++11中,有一种新的方法在用new运算符申请结构体内存的同时对其初始化。其格式为:

struct car{
    int years;
    double price;
};

car * p = new car{3, 23.5};

但是如果结构体中包含了字符数组(字符串),就不能使用这种格式,例如:

struct car{
    char name [20];
    double price;
};

car c {"Ford", 23.4};   //合法,在声明的时候可以用字符串的形式对数组进行初始化
car * p = new car {"Ford", 23.4};//非法,无法用该参数列表构造出car,不能将字符串转换成字符数组
car *c = new car{{'F','o','r','d'}, 23.4};//合法,用数组的形式传入参数,而不是字符串形式

造成这一错误的原因是因为,在new调用car的构造函数时,不能将字符串形式的参数转换成字符数组。

函数不能返回指向本地变量的指针

我们可以在函数中返回一个指针,但是该指针并不是可以指向任何它想指的地址。如果一不小心指向了被调用函数中的本地变量,等到函数返回之后,指针还是会指向函数中本地变量的地址,但是该地址已经被回收,等到下一次要使用栈的时候就会被分配出去,这时如果其他函数对该地址中的内容进行修改,就会发生数据混乱。例如:

int * inner(){
    int * p, x = 1;
    p = &x;
    return p;
}

void another(){
    int * p, x = 34;
    p = &x;
}

int main(void){
    int * p = inner();
    printf("%d\n",*p);
    another();
    printf("%d\n",*p);
}

这里先调用inner()并返回了一个指向其本地变量的指针。在函数执行完毕并返回之后,变量x的内存被回收,但是并没有改变其中的内容(具体可以去看操作系统相关内容),并且指针还是指向了这一块内存,所以即使函数退出,变量销毁之后,还是能访问到该变量的值。

但是后面有调用了另一个函数another(),该函数需要申请的内存跟inner()完全一样,所以在inner()对栈内存进行申请之后,inner()中的xanother()中的x其实是同一个地址。在inner()中修改了该地址中的内容之后,指针p指向内存的内容也发生了改变。

函数返回本地变量

《C++ Primer Plus》上面说当函数返回一个本地对象作为返回值的时候,编译器将复制本地对象,再将其返回。但是我自己做实验的时候,情况却不是这样:

class Stock{
	private:
		double price;
	
	public:
		Stock(){
			cout << "Using default constructor." << endl;
		}
		Stock(double);
		Stock(const Stock &);
		void show() const;
		double getPrice() const;
};

Stock::Stock(double p){
	price = p;
	cout << "Initializing instance for " << price << endl;
}

Stock::Stock(const Stock & s){
	cout << "Using copy constructor for " << s.price << endl;
}

void Stock::show() const{
	cout << "Stock price is: " << price << endl;
}

double Stock::getPrice() const{
	return price;
}

Stock sum(const Stock & s1, const Stock & s2){
	Stock res(s1.getPrice() + s2.getPrice());
	cout << "Instance address in function is: " << &res << endl;    //打印本地变量的地址
	return res;
}

Stock s1(2);
Stock s2(3);
Stock res = sum(s1, s2);
Stock cp = res;
cout << "Instance address outside function is: " << &res << endl;   //打印调用函数范文内接收返回变量的地址
res.show();

上面的代码创建了两个Stock类,并定义了一个函数将两个Stcok.price,并且新建了一个本地对象用于存储相加后的值,返回值就是这个本地变量。但是程序运行之后,函数返回值的地址跟函数内本地对象的地址一样,并且函数返回的时候系统也没有调用Stock类的复制构造函数。这可能是编译器对于函数返回对象这一行为做的内存优化。

如果函数返回的不是一个对象,而是一个原始类型,就不会出现上面的情况:

int test(){
	int x = 3;
	cout << "Address in the function is: " << &x << endl;
	return x;
}

int x = test();
cout << "Address outside the function is: " << &x << endl;

在这个程序里,两个变量的地址不一样。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值