精华内容
下载资源
问答
  • 类的指针成员的初始化
    千次阅读
    2017-09-19 19:57:54

    还记得工作两年多跳槽到北京某浏览器公司,从后端j2ee改行做了c++,虽然以前学过,但是实践做起项目来,实在是艰难,尤其是整个webkit项目非常庞大,一时间手足无措。

    那时候遇到了很多莫名其妙的问题,记忆犹新的就是这个类指针成员初始化的问题。

    简单的描述就是:

    类有一个指针成员变量,它并不会自己初始化为0,所以一般需要在构造函数初始化列表中显示初始化为0,如果不这么做,而在其它地方又做了非0判断,或直接使用,就会出现野指针,而出错的信息会非常奇怪,无法跟踪。



    更多相关内容
  • C++类指针初始化

    千次阅读 2017-12-29 14:22:17
    初始化为NULL的类指针可以安全的调用不涉及类成员变量的类成员函数而不出错,但是如果类成员函数中调用了类成员变量则会出错,既然赋值为NULL的情况都可以使用,那么自然不初始化类指针同样满足这情况。...
    上面 的代码会打印“A”。
    C++ 类指针定义的时候没有初始化的时候,居然可以安全的调用类内部的成员函数而不出错。
    在网上查了一下:

    初始化为NULL的类指针可以安全的调用不涉及类成员变量的类成员函数而不出错,但是如果类成员函数中调用了类成员变量则会出错,既然赋值为NULL的情况都可以使用,那么自然不初始化的类指针同样满足这类情况。
    假设现在有一个简单的类定义如下:
    class Test
    {
    public:
        void func(){cout << "hahaha" << endl;}
        int get(){return a+b;}
        Test():a(1),b(2){}
    public:
        int a,b;
    };

    而之后编译器会自动将这个类转换成:
    class Test
    {
        int a,b;
    };
    void _test_func(Test * this);
    int _test_get(Test* this);
    ........



    类中的函数被编译器静态编译了,所有非虚函数(虚函数呢?别急,待会会解释到)都可以调用,因为函数地址编译期间已经确定。我们知道,类中的成员函数都是通过this指针调用成员变量的,编译器会将this指针作为默认参数传给类成员函数的,如myclass.function(int a,int b) --> function(&myclass,int a,int b)
    添加main函数如下:
    int main()
    {
    Test *p=NULL;
    p->func();//正确,没有调用成员变量,没有使用空的this指针
    p->get();//错误,this指针为空,通过this指针调用变量所以出错
    return 0;
    }

    运行结果如上,没有调用成员变量的func()函数正确执行,调用了成员变量的get()函数错误。两者其实都传入了空的this指针,前者没出错仅仅是因为没有调用this指针,而后者调用了。(此时p-func()和p->get()等同于func(NULL),get(NULL)......)是对象指针为NULL,而调用成员函数的时候,函数地址是编译期间确定的,成员函数不通过对象指针(也即当前的p指针)去调用,对象指针仅仅作为参数传入函数然后去调用成员变量。
          好现在问题来了,如果是虚函数呢,因为虚函数要通过this指针计算vptr,然后找到vtable,然后dispatch。因为this指针为空,所以在找vtable时候就会coredump了。总之这类情况下,一切调用了this指针的函数都会出错,而完全不调用this指针的成员函数则没问题。
    总结:任何时候定义指针的时候一定要初始化,这是良好的习惯,这个问题最初是由于当时写程序疏忽造成的,然而错有错着居然编译通过,所以当时一直没发现这个手误,现在追本溯源也算是对c++的内部机制有了更深的了解,不过也提示自己不能有侥幸心理,一定要养成良好的编程习惯,不管对于自己还是对于以后合作的伙伴都是一件好事。
    展开全文
  • 结构体的指针成员初始化问题

    千次阅读 2020-02-03 11:09:45
    所有成员变量的值都是0 , char [10] 型 "\0", int 是 0, struct Node * 是NULL。 声明为全局量,会自动初始化为上述值。 typedef struct cacheEntryS { int key; /* 数据的key */ int value; /* 数据的data */....

    memset(cache, 0, sizeof(*cache));

    所有成员变量的值都是0 , char [10] 型 "\0", int 是 0, struct Node * 是 NULL 。
    声明为全局量,会自动初始化为上述值。

    typedef struct cacheEntryS {
    	int key;   /* 数据的key */
    	int value;  /* 数据的data */
    
    	struct cacheEntryS* hashListPrev;   /* 缓存哈希表指针, 指向哈希链表的前一个元素 */
    	struct cacheEntryS* hashListNext;   /* 缓存哈希表指针, 指向哈希链表的后一个元素 */
    
    	struct cacheEntryS* lruListPrev;    /* 缓存双向链表指针, 指向链表的前一个元素 */
    	struct cacheEntryS* lruListNext;    /* 缓存双向链表指针, 指向链表后一个元素 */
    }cacheEntryS;

        cacheEntryS* en = malloc(sizeof(*en));
        en->key = key;
        en->value = value;
        en->hashListNext = NULL;
        en->hashListPrev = NULL;

     

    leetcode -bug   :member access within misaligned address,按照上面的叙述,貌似不需要专门为指针设置为空,memset已经完成了工作,但是leetcode依然会报错。

        需要加上以下两句,才会显示正确:

        en->hashListNext = NULL;
        en->hashListPrev = NULL;

     

    C语言结构体里的成员数组和指针

    https://coolshell.cn/articles/11377.html

    单看这文章的标题,你可能会觉得好像没什么意思。你先别下这个结论,相信这篇文章会对你理解C语言有帮助。这篇文章产生的背景是在微博上,看到@Laruence同学出了一个关于C语言的题,微博链接。微博截图如下。我觉得好多人对这段代码的理解还不够深入,所以写下了这篇文章。

    zero_array

    为了方便你把代码copy过去编译和调试,我把代码列在下面:

     

    #include <stdio.h>

    struct str{

    int len;

    char s[0];

    };

    struct foo {

    struct str *a;

    };

    int main(int argc, char** argv) {

    struct foo f={0};

    if (f.a->s) {

    printf( f.a->s);

    }

    return 0;

    }

     

    你编译一下上面的代码,在VC++和GCC下都会在14行的printf处crash掉你的程序。@Laruence 说这个是个经典的坑,我觉得这怎么会是经典的坑呢?上面这代码,你一定会问,为什么if语句判断的不是f.a?而是f.a里面的数组?写这样代码的人脑子里在想什么?还是用这样的代码来玩票?不管怎么样,看过原微博的回复,我个人觉得大家主要还是对C语言理解不深,如果这算坑的话,那么全都是坑。

     

    接下来,你调试一下,或是你把14行的printf语句改成:

     

    printf("%x\n", f.a->s);

    你会看到程序不crash了。程序输出:4。 这下你知道了,访问0x4的内存地址,不crash才怪。于是,你一定会有如下的问题:

    1)为什么不是 13行if语句出错?f.a被初始化为空了嘛,用空指针访问成员变量为什么不crash?

    2)为什么会访问到了0x4的地址?靠,4是怎么出来的?

    3)代码中的第4行,char s[0] 是个什么东西?零长度的数组?为什么要这样玩?

    让我们从基础开始一点一点地来解释C语言中这些诡异的问题。

    目录

    结构体中的成员

    首先,我们需要知道——所谓变量,其实是内存地址的一个抽像名字罢了。在静态编译的程序中,所有的变量名都会在编译时被转成内存地址。机器是不知道我们取的名字的,只知道地址。

    所以有了——栈内存区,堆内存区,静态内存区,常量内存区,我们代码中的所有变量都会被编译器预先放到这些内存区中。

    有了上面这个基础,我们来看一下结构体中的成员的地址是什么?我们先简单化一下代码:

     

    struct test{

    int i;

    char *p;

    };

     

    上面代码中,test结构中i和p指针,在C的编译器中保存的是相对地址——也就是说,他们的地址是相对于struct test的实例的。如果我们有这样的代码:

     

    struct test t;

    我们用gdb跟进去,对于实例t,我们可以看到:

     

    # t实例中的p就是一个野指针

    (gdb) p t

    $1 = {i = 0, c = 0 '\000', d = 0 '\000', p = 0x4003e0 "1\355I\211\..."}

    # 输出t的地址

    (gdb) p &t

    $2 = (struct test *) 0x7fffffffe5f0

    #输出(t.i)的地址

    (gdb) p &(t.i)

    $3 = (char **) 0x7fffffffe5f0

    #输出(t.p)的地址

    (gdb) p &(t.p)

    $4 = (char **) 0x7fffffffe5f4

     

    我们可以看到,t.i的地址和t的地址是一样的,t.p的址址相对于t的地址多了个4。说白了,t.i 其实就是(&t + 0x0)t.p 的其实就是 (&t + 0x4)。0x0和0x4这个偏移地址就是成员i和p在编译时就被编译器给hard code了的地址。于是,你就知道,不管结构体的实例是什么——访问其成员其实就是加成员的偏移量

    下面我们来做个实验:

     

    struct test{

    int i;

    short c;

    char *p;

    };

    int main(){

    struct test *pt=NULL;

    return 0;

    }

     

    编译后,我们用gdb调试一下,当初始化pt后,我们看看如下的调试:(我们可以看到就算是pt为NULL,访问其中的成员时,其实就是在访问相对于pt的内址)

     

    (gdb) p pt

    $1 = (struct test *) 0x0

    (gdb) p pt->i

    Cannot access memory at address 0x0

    (gdb) p pt->c

    Cannot access memory at address 0x4

    (gdb) p pt->p

    Cannot access memory at address 0x8

     

    注意:上面的pt->p的偏移之所以是0x8而不是0x6,是因为内存对齐了(我在64位系统上)。关于内存对齐,可参看《深入理解C语言》一文。

    好了,现在你知道为什么原题中会访问到了0x4的地址了吧,因为是相对地址。

    相对地址有很好多处,其可以玩出一些有意思的编程技巧,比如把C搞出面向对象式的感觉来,你可以参看我正好11年前的文章《用C写面向对像的程序》(用指针类型强转的危险玩法——相对于C++来说,C++编译器帮你管了继承和虚函数表,语义也清楚了很多)

    指针和数组的差别

    有了上面的基础后,你把源代码中的struct str结构体中的char s[0];改成char *s;试试看,你会发现,在13行if条件的时候,程序因为Cannot access memory就直接挂掉了。为什么声明成char s[0],程序会在14行挂掉,而声明成char *s,程序会在13行挂掉呢?那么char *s 和 char s[0]有什么差别呢

    在说明这个事之前,有必要看一下汇编代码,用GDB查看后发现:

    • 对于char s[0]来说,汇编代码用了lea指令,lea   0x04(%rax),   %rdx
    • 对于char*s来说,汇编代码用了mov指令,mov 0x04(%rax),   %rdx

    lea全称load effective address,是把地址放进去,而mov则是把地址里的内容放进去。所以,就crash了。

    从这里,我们可以看到,访问成员数组名其实得到的是数组的相对地址,而访问成员指针其实是相对地址里的内容(这和访问其它非指针或数组的变量是一样的)

    换句话说,对于数组 char s[10]来说,数组名 s 和 &s 都是一样的(不信你可以自己写个程序试试)。在我们这个例子中,也就是说,都表示了偏移后的地址。这样,如果我们访问 指针的地址(或是成员变量的地址),那么也就不会让程序挂掉了。

    正如下面的代码,可以运行一点也不会crash掉(你汇编一下你会看到用的都是lea指令):

     

    struct test{

    int i;

    short c;

    char *p;

    char s[10];

    };

    int main(){

    struct test *pt=NULL;

    printf("&s = %x\n", pt->s); //等价于 printf("%x\n", &(pt->s) );

    printf("&i = %x\n", &pt->i); //因为操作符优先级,我没有写成&(pt->i)

    printf("&c = %x\n", &pt->c);

    printf("&p = %x\n", &pt->p);

    return 0;

    }

     

    看到这里,你觉得这能算坑吗?不要出什么事都去怪语言,大家要想想是不是问题出在自己身上。

    关于零长度的数组

    首先,我们要知道,0长度的数组在ISO C和C++的规格说明书中是不允许的。这也就是为什么在VC++2012下编译你会得到一个警告:“arning C4200: 使用了非标准扩展 : 结构/联合中的零大小数组”。

    那么为什么gcc可以通过而连一个警告都没有?那是因为gcc 为了预先支持C99的这种玩法,所以,让“零长度数组”这种玩法合法了。关于GCC对于这个事的文档在这里:“Arrays of Length Zero”,文档中给了一个例子(我改了一下,改成可以运行的了):

     

    #include <stdlib.h>

    #include <string.h>

    struct line {

    int length;

    char contents[0]; // C99的玩法是:char contents[]; 没有指定数组长度

    };

    int main(){

    int this_length=10;

    struct line *thisline = (struct line *)

    malloc (sizeof (struct line) + this_length);

    thisline->length = this_length;

    memset(thisline->contents, 'a', this_length);

    return 0;

    }

     

    上面这段代码的意思是:我想分配一个不定长的数组,于是我有一个结构体,其中有两个成员,一个是length,代表数组的长度,一个是contents,代码数组的内容。后面代码里的 this_length(长度是10)代表是我想分配的数据的长度。(这看上去是不是像一个C++的类?)这种玩法英文叫:Flexible Array,中文翻译叫:柔性数组。

    我们来用gdb看一下:

     

    (gdb) p thisline

    $1 = (struct line *) 0x601010

    (gdb) p *thisline

    $2 = {length = 10, contents = 0x601010 "\n"}

    (gdb) p thisline->contents

    $3 = 0x601014 "aaaaaaaaaa"

     

    我们可以看到:在输出*thisline时,我们发现其中的成员变量contents的地址居然和thisline是一样的(偏移量为0x0??!!)。但是当我们输出thisline->contents的时候,你又发现contents的地址是被offset了0x4了的,内容也变成了10个‘a’。(我觉得这是一个GDB的bug,VC++的调试器就能很好的显示)

    我们继续,如果你sizeof(char[0])或是 sizeof(int[0]) 之类的零长度数组,你会发现sizeof返回了0,这就是说,零长度的数组是存在于结构体内的,但是不占结构体的size。你可以简单的理解为一个没有内容的占位标识,直到我们给结构体分配了内存,这个占位标识才变成了一个有长度的数组。

    看到这里,你会说,为什么要这样搞啊,把contents声明成一个指针,然后为它再分配一下内存不行么?就像下面一样。

     

    struct line {

    int length;

    char *contents;

    };

    int main(){

    int this_length=10;

    struct line *thisline = (struct line *)malloc (sizeof (struct line));

    thisline->contents = (char*) malloc( sizeof(char) * this_length );

    thisline->length = this_length;

    memset(thisline->contents, 'a', this_length);

    return 0;

    }

     

    这不一样清楚吗?而且也没什么怪异难懂的东西。是的,这也是普遍的编程方式,代码是很清晰,也让人很容易理解。即然这样,那为什么要搞一个零长度的数组?有毛意义?!

    这个事情出来的原因是——我们想给一个结构体内的数据分配一个连续的内存!这样做的意义有两个好处:

    第一个意义是,方便内存释放。如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。(读到这里,你一定会觉得C++的封闭中的析构函数会让这事容易和干净很多)

    第二个原因是,这样有利于访问速度。连续的内存有益于提高访问速度,也有益于减少内存碎片。(其实,我个人觉得也没多高了,反正你跑不了要用做偏移量的加法来寻址)

    我们来看看是怎么个连续的,用gdb的x命令来查看:(我们知道,用struct line {}中的那个char contents[]不占用结构体的内存,所以,struct line就只有一个int成员,4个字节,而我们还要为contents[]分配10个字节长度,所以,一共是14个字节)

     

    (gdb) x /14b thisline

    0x601010: 10 0 0 0 97 97 97 97

    0x601018: 97 97 97 97 97 97

     

    从上面的内存布局我们可以看到,前4个字节是 int length,后10个字节就是char contents[]。

    如果用指针的话,会变成这个样子:

     

    (gdb) x /16b thisline

    0x601010: 1 0 0 0 0 0 0 0

    0x601018: 32 16 96 0 0 0 0 0

    (gdb) x /10b this->contents

    0x601020: 97 97 97 97 97 97 97 97

    0x601028: 97 97

     

    上面一共输出了四行内存,其中,

    • 第一行前四个字节是 int length,第一行的后四个字节是对齐。
    • 第二行是char* contents,64位系统指针8个长度,他的值是0x20 0x10 0x60 也就是0x601020。
    • 第三行和第四行是char* contents指向的内容。

    从这里,我们看到,其中的差别——数组的原地就是内容,而指针的那里保存的是内容的地址

    后记

    好了,我的文章到这里就结束了。但是,请允许我再唠叨两句。

    1)看过这篇文章,你觉得C复杂吗?我觉得并不简单。某些地方的复杂程度不亚于C++。

    2)那些学不好C++的人一定是连C都学不好的人。连C都没学好,你们根本没有资格鄙视C++。

    3)当你们在说有坑的时候,你得问一下自己,是真有坑还是自己的学习能力上出了问题。

    展开全文
  • 组合 类指针对象的初始化

    千次阅读 2020-10-23 16:40:15
    的组合 构造函数的用法 在一个中内嵌另一个的对象作为数据成员,称为的组合。该内嵌对象称为对象成员...在使用过程中,需要着重注意的是对象成员初始化!如Triangle的构造函数该如何定义? 如果一个具...

    类的组合 构造函数的用法

    在一个类中内嵌另一个类的对象作为数据成员,称为类的组合。该内嵌对象称为对象成员,或者子对象。如三角形类Triangle类的内嵌Node类作为数据成员;

     

    class Triangle
    {
    private:
        Node *nodei;  //对象成员
        Node *nodej;
        Node *nodem;
    public:
        ...
    };

     

    在使用过程中,需要着重注意的是 对象成员的初始化!如Triangle的构造函数该如何定义?

    如果一个类具有内嵌对象,那么在它对象化的时候既要对基本数据成员初始化也要对内嵌的对象成员初始化。

     

    class X
    
    {
      类名1  对象成员名1;
      类名2  对象成员名2;
      ...
      类名n  对象成员名n;
    };

    一般来说类X的构造函数定义形式为:

    X::X(形参表0):对象成员名1(形参1),...,对象成员名n(形参n)
    {
    
      类X的构造函数体
    
    }

    形参1到n一般来自形参表0;而且当调用构造函数的时候,首先按照在类的声明中的顺序依次调用对象成员函数的构造函数,对这些对象初始化,最后执行够赞函数体初始化类中的其他数据成员;析构函数的调用顺序与构造函数相反!举例说明:

    复制代码

    #include<iostream>
    using namespace std;
    class Node
    {
    private:
        double x_;
        double y_;
    public:
        Node(double x=0,double y=0)    //带默认参数的构造函数
        {
            x_=x;
            y_=y;
            cout<<"x="<<x_<<endl;
        }
        ~Node()                        //Node类的析构函数
        {
            cout<<"x="<<x_<<endl;
        }
    };
    class Triangle
    {
    private:
        Node nodei;
        Node nodej;
        Node nodem;
    public:
        Triangle(double a1,double b1,double a2,double b2,double a3,double b3):nodei(a1,b1),
            nodej(a2,b2),nodem(a3,b3)//内嵌对象成员的Triangle类的构造函数定义
        {}
        ~Triangle()                     //Triangle类析构函数
        {}
    };
    int main()
    {
        Triangle tri(1,1,2,2,3,3);     //初始化
        return 0;
    }

    复制代码

    输出结果:

     

    说明:如果类的内嵌对象是用指针表示的,如何初始化呢?这个时候用上述的初始化列表就失效了!

    复制代码

    #include<iostream>
    using namespace std;
    class Node
    {
    private:
        double x_;
        double y_;
    public:
        Node(double x=0,double y=0)    //带默认参数的构造函数
        {
            x_=x;
            y_=y;
            cout<<"x="<<x_<<endl;
        }
        void init(double x,double y)//自定义初始化函数
        {
            x_=x;
            y_=y;
        }
        ~Node()                        //Node类的析构函数
        {
            cout<<"x="<<x_<<endl;
        }
        void disp(void)                //输出函数
        {
            cout<<"x="<<x_<<endl;
        }
    };
    class Triangle
    {
    private:
        Node *nodei;                //数据成员为指向Node类型的指针
        Node *nodej;
        Node *nodem;
    public:
        Triangle(double a1,double b1,double a2,double b2,double a3,double b3)
        {
            Node *node1,*node2,*node3;    
            //定义参量指针
            node1=new Node;            //动态分配内存
            node2=new Node;
            node3=new Node;
            node1->init(a1,b1);        //调用自定义init()初始化三个点
            node2->init(a2,b2);
            node3->init(a3,b3);
            nodei=node1;            //再将初始化也即分配了内存后的指针值赋给数据成员
            nodej=node2;
            nodem=node3;
            nodei->disp();            //打印赋值结果
            nodej->disp();
            nodem->disp();
            //delete node3;            //释放指针所指
            //delete node2;
            //delete node1;
    
        }
        ~Triangle()                     //Triangle类析构函数
        {
    
        }
        void disp()
        {
            nodei->disp();
            nodej->disp();
            nodem->disp();
        }
    };
    int main()
    {
        Triangle tri(1,1,2,2,3,3);     //初始化
        tri.disp();
        return 0;
    }

    复制代码

    输出结果为:

    显然这样定义构造函数既不直观(不知道那个参数对应那个点)也很麻烦!改为如下:

    复制代码

    #include<iostream>
    using namespace std;
    class Node
    {
    private:
        double x_;
        double y_;
    public:
        Node(double x=0,double y=0)    //带默认参数的构造函数
        {
            x_=x;
            y_=y;
            cout<<"x="<<x_<<endl;
        }
        void init(double x,double y)//自定义初始化函数
        {
            x_=x;
            y_=y;
        }
        ~Node()                        //Node类的析构函数
        {
            cout<<"x="<<x_<<endl;
        }
        void disp(void)                //输出函数
        {
            cout<<"x="<<x_<<endl;
        }
    };
    class Triangle
    {
    private:
        Node *nodei;                //数据成员为指向Node类型的指针
        Node *nodej;
        Node *nodem;
    public:
        Triangle(Node& node1,Node& node2,Node& node3)
        {
            //nodei=new Node;            //动态分配内存
            //nodej=new Node;
            //nodem=new Node;
            nodei=&node1;        //地址传递
            nodej=&node2;
            nodem=&node3;
            nodei->disp();            //打印赋值结果
            nodej->disp();
            nodem->disp();
            //delete node3;            //释放指针所指
            //delete node2;
            //delete node1;
    
        }
        ~Triangle()                     //Triangle类析构函数
        {
    
        }
        void disp()
        {
            nodei->disp();
            nodej->disp();
            nodem->disp();
        }
    };
    int main()
    {
        Node nod1(1,1),nod2(2,2),nod3(3,3);
        Triangle tri(nod1,nod2,nod3);     //初始化
        //tri.disp();
        return 0;
    }

    复制代码

    输出:

    这样来定义构造函数既没有用到init()自定义的初始化函数,而且物理意义明确。

     

    总结:1.有子对象的类的初始化问题。子对象不是直接用类名表示,可以用初始化列表初始化。

       2.如果子对象用指针形式表示,就不能用初始化列表了。

     

    展开全文
  • C++ 静态成员初始化详解及实例代码 一般来说,关于C++静态成员初始化,并不会让人感到难以理解,但是提到C++ 静态成员的”初始化”那就容易迷糊了。 我们来看如下代码: //example.h #include #...
  • C++类成员指针没有被初始化

    千次阅读 2018-09-28 17:48:14
    最近经常犯的一个小错误: 即当内部成员属性为指针时,记得一定要进行初始化,否则会出现随机值,野指针的问题。
  • c语言结构体指针初始化

    千次阅读 2021-05-21 07:15:48
    今天终于看完了C语言深度剖析这本书,对C语言有了进一步的了解与感悟,突然发觉原来自己学C语言的时候学得是那样的迷糊,缺少深入的...定义了指针变量,没有为指针分配内存,即指针没有在内存中指向一块合法的内存...
  • C++中的数据成员如何初始化

    千次阅读 2020-03-10 18:25:10
    C++中的数据成员初始化,首先需要明白在中都有哪些数据成员 const成员:也就是常量成员,它们在声明时就要初始化,因为它们为常量成员,一旦定义,就不能修改 引用成员&:引用代表的就是被引用者自身,是...
  • C语言指针初始化情况

    千次阅读 2021-05-21 04:44:57
    在栈上开辟的结构体,为初始化时,其成员变量无论原始类型或指针类型值都为0; 在堆上用malloc开辟的空间,成员变量值为0;开辟的连续空间,如 int *arr = (int*)malloc(sizeof(int)*3) 每一个元素值为“乱数” ...
  • C 结构体指针初始化

    万次阅读 2019-04-26 23:18:31
    原文 C 结构体指针初始化,CSDN同步发布。 转载请注明出处,谢谢! 在使用指针之前,务必要将其初始化。这个是我们最早学习 C 语言的时候,书上经常说的一个问题。在工作中,我们反而会经常忘记这条金科玉律。 本篇...
  • 指针初始化和赋值(简单说明)

    千次阅读 2021-06-18 15:23:21
    突然关于指针有个地方搞不明白,比如int *p=&a;我们不是说"*"是取值的吗,那么后面不应该跟的是一个数值,怎么是一个地址?
  • C++中的指针初始化

    万次阅读 2019-08-04 21:22:56
    需要对指针本身和指针的指向都进行初始化,既要初始化内存地址,也要定义内存中的内容。如果不进行指针初始化,则内存地址随机分配。格根据编译器的不同,会出现警告或者报错不同等级的问题,在编译中也可能出现...
  • 初始化: 1.通过构造函数初始化 代码如下: std::shared_ptr<T> 智能指针名字(创建堆内存) 2.通过拷贝和移动构造函数初始化 代码如下: #include <iostream> #include <memory> using namespace std...
  • 结构体里面的函数指针怎么初始化

    千次阅读 2018-12-27 14:49:48
    * 为结构体中的指针数组赋值 */ #include &lt;stdio.h&gt; typedef struct test { void (*p)(void); void (*q)(void); void (*y)(void); }test; void f1(void) { printf("f1\n"); } ...
  • c++指针初始化问题

    万次阅读 多人点赞 2018-12-13 11:47:18
    c++中的指针是一个很经典的用法,但是也是最容易出错的,比如定义了一个指针,必须对其进行初始化,不然这个指针指向的是一个未知的内存地址,后续对其操作的时候,会报错。这只是其次,最让人头疼的就是指针错误...
  • 含有对象成员指针的对象成员指针初始化问题 [问题点数:20分,结帖人papaweilun] https://bbs.csdn.net/topics/392257006 收藏帖子 回复 hereIambabe 结帖率 66.67% 为什么这个中的两个coordinate的...
  • 指针成员的内存分配和初始化

    千次阅读 2014-12-20 15:39:09
    指针是出现错误的一大来源,如果在中定义指针成员,在使用过程中必须十分小心; 如果在使用的过程中采用动态分配内存的方式,其问题似乎变得愈加复杂。 先定义一个测试: class Cptr { public: std::...
  • C++和对象(下)——初始化列表、static成员和友元

    千次阅读 多人点赞 2021-03-08 09:23:18
    C++和对象——初始化列表、static成员和友元一、再谈构造函数1.1 构造函数整体赋值1.2 初始化列表三级目录 关于C++和对象的学习 C++和对象(上)——的基本概念、的限定符及封装和类成员函数的this指针 C++...
  • c++中双指针初始化

    千次阅读 2018-07-23 10:27:15
    指针初始化: 字符串双指针初始化: char **text = new char*[512]; for (int i = 0; i &lt; 512; i++) { text[i] = new char[1024]; } 整型双指针初始化: int **temp; int i = 0; //初始化 temp ...
  • 结构体指针变量初始化问题

    千次阅读 2020-12-08 17:52:08
    这段代码不能初始化innrtc这个结构体成员,原因是因为初始化的这些值只是对指针赋值,并没有赋值到指针地址下的变量。innrtc相当于野指针。 2,下面的代码是正确的: //file1.c代码不变 //file2.c代码如下 struct ...
  • struct student{char * name; int score;}stu, *pstu;int main(){strcpy(stu.name, 'Jimy'); stu.score = 90;...答:定义的结构体变量stu,分配了char *类型的指针指针变量name本身只分配了4个字节)和int...
  • C++指针初始化注意问题

    千次阅读 2018-09-01 11:12:06
    C++指针初始化注意问题 首先了解一下编译器自动生成的赋值函数和operator =函数, 如果你成员变量没有指针那么没什么问题,自带的copy函数会逐bits 的copy,但是如果你中定义了指针那么问题大了,他会很傻傻...
  • c语言结构体指针成员初始化

    千次阅读 2013-04-01 12:29:44
    今天遇到一个奇怪的问题,错误提示段错误,明显是指针操作有问题。找了N久才把问题定位在自定义的链表上。next指针一直有数据。 struct S{ void (*call)(); S *next; };上面一个简单的结构体,在程序中: ...
  • 成员变量必须在构造函数的初始化列表中完成初始化。Smart pointer members minimize dependencies while allowing exception safety。  通过以指针存储成员变量的方法最小化依赖  当成员变量的头文件非常大或者...
  • 智能指针一定要初始化

    千次阅读 2018-05-21 09:50:53
    转载。今天写程序,智能指针又忘了初始化。特此记下,增加印象,一给我里giaogiao!
  • 智能指针的三种初始化方法

    千次阅读 2020-12-08 09:50:52
    //初始化方式1 std::shared_ptr<int> sp1(new int(123)); //初始化方式2 std::shared_ptr<int> sp2; sp2.reset(new int(123)); //初始化方式3 std::shared_ptr<int> sp3; sp3 = std::make_...
  • 结构体成员和结构体指针初始化

    千次阅读 2018-06-28 11:38:22
    结构体指针成员指针同样需要初始化*/ //stu.next = stu1; strcpy(stu1->name,"Lucy"); stu1->score = 98; stu1->next = NULL; printf("name %s, score %d \n ",stu.name, stu.score); printf(...
  • 成员变量必须在构造函数的初始化列表中完成初始化。Smart pointer members minimize dependencies while allowing exceptiON safety。  通过以指针存储成员变量的方法化依赖  当成员变量的头文件非常大或者非常...
  • c语言结构体学习整理(结构体初始化,结构体指针)

    万次阅读 多人点赞 2018-11-01 20:22:12
    我们都已经学了很多int char …等类型还学到了同类型元素构成的数组,以及取上述类型的指针,在一些小应用可以灵活使用,然而,在我们实际应用中,每一种变量进行一次声明,再结合起来显然是不太实际的,如一位...
  • 结构体指针需要初始化

    千次阅读 2019-02-22 21:43:00
    结构体指针成员指针同样需要初始化*/ stu.next = stu1; strcpy(stu1->name,"Lucy"); stu1->score = 98; stu1->next = NULL; printf("name %s, score %d \n ",stu.name, stu.score); printf("name %s, ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 293,061
精华内容 117,224
关键字:

类的指针成员的初始化