关于友元函数的使用练习

#include <stdio.h>

class vector{
    public:
        vector(float x,float y);
        // if there is no "friend", we can set only one argument.
           friend vector operator +(const vector &v1, const vector &v2);
        vector & operator =(const vector &v);
        void show();
    private:
    float x;
    float y;   
};
vector::vector(float x,float y){
    this->x = x;
    this->y = y;
}
// friend function's definition has not "vector::"
vector operator +(const vector &v1, const vector &v2){
    vector vv(0,0);
    vv.x = v1.x+v2.x;
    vv.y = v1.y+v2.y;
    return vv;
}
vector & vector::operator =(const vector &v){
    this->x = v.x;
    this->y = v.y;
    return *this;
}
void vector::show(){
    printf("(%f,%f)\n",this->x,this->y);
}
int main(){
    vector vec1(10,20);
    vector vec2(100,200);
    vec1 = vec1+vec2;
    vec1.show();
    vec2.show();   
    return 0;
}

函数中的堆,栈,数据段内存使用

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *getstr();

int main(){
    printf("%s\n",getstr());
    return 0;
}

char *getstr(){
    //char str[] = "hello world"; //return local stack memory variable. dangerous.
    //char *str = "hello world";  //str point to data segment memory. ok
    char *str = (char *)malloc(12); //heap memory. ok
    strcpy(str,"hello world");
    return str;   
}

char *str = "hello world"中的字符串存储在静态存储区。
对于printf("%s\n",getstr());,getstr函数结束后,栈内存回收处理,存储的字符串被破坏了。

Temporary breakpoint 2, main () at malloc.c:8
8        char *s = getstr();
(gdb) n
9        printf("%s\n",s);
(gdb) p s
$2 = 0xbffff1ec "hello world"
(gdb) n
@�����rld
10        return 0;
(gdb) p s
$3 = 0xbffff1ec "@\204\004\b\354\361\377\277rld"

调试器展示了指针s指向的地址一样,但是存储值前后不一样。
getstr函数中的str会在函数结束后消亡,但是函数内所申请的动态内存不会消失,除非自己free了。

勿用指针参数申请动态内存

看下面的代码,试图用参数p来获得内存。但实际会出现段错误。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void getmem(char *p);
int main(){
    char *point = NULL;
    getmem(point);       
    strcpy(point,"hello world");
    puts(point);
    return 0;
}

void getmem(char *p){
    p = (char *)malloc(12*sizeof(char));
}

编译器是这样处理getmem的:创建一个临时的指针_p,使得_p = p,然后_P = (char *)malloc(12*sizeof(char)); ,相当于将_p指向的内存地址改变了,但是p没有变化!
修正:返回申请的内存地址。可以通过二重指针参数或者设置成返回指针的形式。
(1) 二重指针参数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void getmem(char **p);
int main(){
    char *point = NULL;
    getmem(&point);       
    strcpy(point,"hello world");
    puts(point);
    free(point);
    point = NULL;
    return 0;
}

void getmem(char **p){
    *p = (char *)malloc(12*sizeof(char));
}

(2) 返回指针

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void *getmem();
int main(){
    char *point = NULL;
    point = (char *)getmem(&point);       
    strcpy(point,"hello world");
    puts(point);
    free(point);
    point = NULL;
    return 0;
}

void* getmem(){
    return malloc(12*sizeof(char));
}

野指针

指向已经释放或者访问受限的内存区域的指针会成为野指针。free,delete只是将内存释放了,指针仍然指向原来设置的地址。所谓释放内存,只是将内存中存储的值清理了。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
    char *s = (char *)malloc(6*sizeof(char));
    strcpy(s,"12345");
    puts(s);
    free(s);
    puts(s);
    return 0;
}

gdb查看s的状态:

Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.192.el6.i686
(gdb) n
7        strcpy(s,"12345");
(gdb) p s
$1 = 0x804a008 ""
(gdb) n
8        puts(s);
(gdb) p s
$2 = 0x804a008 "12345"
(gdb) n
12345
9        free(s);
(gdb) n
10        puts(s);
(gdb) p s
$3 = 0x804a008 ""

可以发现,s的指向地址不变,但是内存值变了。

结果不可预测的函数

仍然以向量例子实验:

void test(vector **vet){
    vector vec(100,200);
    *vet = &vec;   
}
int main(){
    vector *vec1 = NULL;
    test(&vec1);
    vec1->show();   
    return 0;
}

它的结果每一次都不一样,不可预测。

[edemon@CentOS workspace]$ ./a.out
(0.000000,-1.323352)
[edemon@CentOS workspace]$ ./a.out
(0.000000,-1.091280)
[edemon@CentOS workspace]$ ./a.out
(0.000000,-1.981838)
[edemon@CentOS workspace]$ ./a.out
(0.000000,-1.440334)

用gdb查看:

test (vet=0xbffff20c) at class.cpp:35
35        vector vec(100,200);
(gdb) n
36        *vet = &vec;   
(gdb) n
37    }
(gdb) p vet
$2 = (vector **) 0xbffff20c
(gdb) p *vet
$3 = (vector *) 0xbffff1ec
(gdb) p **vet
$4 = {x = 100, y = 200}
(gdb) n
main () at class.cpp:41
41        vec1->show();   
(gdb) p vec1
$5 = (vector *) 0xbffff1ec
(gdb) p *vec1
$6 = {x = 100, y = 200}
(gdb) n
(0.000000,-1.999570)
42        return 0;
(gdb) p vec1
$7 = (vector *) 0xbffff1ec
(gdb) p *vec1
$8 = {x = 3.98796147e-34, y = -1.99957037}

内存地址不变,但是test函数结束后栈空间被释放,空间内的内容被破坏,指针指向的是无效内存。

分类: career

发表评论

电子邮件地址不会被公开。 必填项已用*标注