类内值初始化问题

0. 前言

昨晚写一个单向链表的代码, 目的是新建几个节点, 然后串联起来, 代码如下:

class ListNode
{
public:
    ListNode(int v):val(v){}
    int val;
    ListNode *next;
    static void print_node_val (const ListNode* p_node){

        while(p_node != nullptr){
            cout << p_node->val;
            p_node = p_node->next;
            if(p_node){
                cout << "->";
            }
            else{
                cout << ";";
            }

        }
        cout << endl;
    }
};

int main(int argc, char *argv[])
{
    //############################################//
    //################   创建链表   ####################//
    //############################################//
    ListNode l1(1);
    ListNode l2(1);
    ListNode l3(2);
    l1.next = &l2;
    l2.next = &l3;

    return 0;
}

代码编译通过, 但是运行的时候出现段错误.
目测是出现了访问非法内存,
然后尝试打印一下地址:

cout << l1.next << endl;
cout << l2.next << endl;
cout << l3.next << endl;

得到:

0x7ffe1b26aee0
0x7ffe1b26aef0
0x55c8295af7f0

果然是初始化的问题, 类的指针没有被初始化为nullptr, 于是在类中的构造函数里加了初始化:

class ListNode
{
public:
    ListNode(int v):val(v), next(nullptr){}
    int val;
    ...

这样话打印就正常了,

0x7ffd0ae20d10
0x7ffd0ae20d20
0

类中的静态成员函数也可以正常使用了.


一开始没加的话, 因为最后的l3while(p_node != nullptr)这里不会终止, 而是继续下去, 这样子访问到的内存就是非法的了. 因此会出现段错误.
以后在写构造函数的时候, 都把值给初始化掉吧!!!

1. 回顾一下基础

为了有个更系统的理解, 我写如下代码测试一下:

/*
 * @Author: sanjayzhong
 * @Github: https://github.com/sanjayzzzhong
 * @Date: 2019-12-16 10:34:35
 */
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <set>

using namespace std;
//############################################//
//################   测试一下带有指针的类的初始化问题   ####################//
//############################################//
class Base{
public:
    int a;
    float b;
    double c;
    Base* next;
    void print(){
        cout << "print" << endl;
    }
    void get(){
        cout << this->a << endl;
    }

};
void test01(){
    //############################################//
    //################   类内普通成员变量不会自动初始化, 给的是随机值   ####################//
    //############################################//
    Base b;
    cout << b.a << endl;
    cout << b.b << endl;
    cout << b.c << endl;
    cout << b.next << endl;
    Base* c = b.next;
    c->a;

    cout << "=============================" << endl << endl;
    //############################################//
    //################   用new来试试: new会自动将值初始化   ####################//
    //############################################//
    Base* new_b = new Base;
    cout << new_b->a << endl;
    cout << new_b->b << endl;
    cout << new_b->c << endl;
    cout << new_b->next << endl;

}
int main(int argc, char *argv[]){
    test01();

    return 0;
}

运行结果如下:

2
0
4.67372e-310
0x7fe46c7fe9a0
=============================

0
0
0
0

首先看=上面部分, 上面部分主要是通过栈内存来声明类, 打印出来的值都是随机值来的, next指针指向的也是随机地址, 不是nullptr;
=下面部分, 可以看到, 通过new创建出来的类, 会默认给初始值, 指针也是给了nullptr(0)

同样, 在栈中申请内存的时候, 虽然编译器有时候会帮我们做优化, 但是更安全的是要自己给初始, 否者的话比较容易出错.


现在问题来了, 为什么new申请堆区的内存会自动帮我们初始化呢?
其实是编译器的原因, gcc/g++在new的时候做了优化.
更正:使用new表达式的时候,new的流程是:

  1. 使用operator new申请内存;
  2. 调用类的构造函数对这块内存进行初始化

用visual studio跑的时候, 上面两种情况都正常!

总结

类构造函数, 要自己把变量都给初始化, 不要依赖编译器!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zedjay_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值