C++ 构造函数之指针的叛逆

C++面试求生指南:从语法糖到内存泄漏的全面突围战 "面试造火箭,工作拧螺丝"——这句在程序员圈子里广为流传的调侃,用在C++面试上再贴切不过。多少程序员在简历上自信满满地写着"精通C++",却在面试官抛出几个看似基础的问题时瞬间破防?从指针乱飞到内存泄漏,从模板特化到多态实现,C++就像一位严苛的老教授,总能在你最意想不到的地方给你当头一棒。本文将带你深入C++面试的"雷区",用幽默风趣的方式剖析那些让程序员闻风丧胆的经典考题。准备好了吗?让我们一起揭开C++面试的神秘面纱! 阅读详情

今天我在这篇博客里记录我做练习遇到的一个BUG,困扰了我两个小时的BUG最后也还是被我解决了。

在这里我简单的举一个例子来列明BUG的所在问题。

需求:
定义一个Human类,里面有private成员:char *name; int age;
再用Human类定义对象h1 。
h1定义时赋初值:h1(“张三”, 30);
最后将其打印出来。

根据需求可以知道,需要自己定义一个重载构造函数

BUG就在自定义的重载构造函数中

下面请看代码:


代码:

Human.h

#pragma once
#include <string>


class Human {
public:
	Human(const char *name=NULL, int age=0);
	~Human();

	std::string description() const;

private:
	char *name;
	int age;
};

Human.cpp

#include <sstream>
#include "Human.h"

// 自定义重载构造函数
Human::Human(const char *nane, int age) {
	// 如果name为空的话,就赋值“无名字”
	if (!name) {
		name = "无名字";
	}

	// 从堆上分配内存给name		
	this->name = new char[strlen(name)+1];

	strcpy_s(this->name, strlen(name)+1, name);	// 深拷贝
	this->age = age;
}

Human::~Human() {
	// 如果name不为空指针,就释放它的内存
	if (name) {
		delete[] name;
	}
}

std::string Human::description() const {
	std::stringstream ret;	// 定义特殊的字符串变量

	ret << "姓名:" << name << "\t年龄:" << age;

	return ret.str();
}

main

#include <iostream>
#include "Human.h"

using namespace std;

int main(void) {
	Human h1("张三", 30);

	cout << h1.description() << endl;

	system("pause");
	return 0;
}

问题就出在Human.cpp文件中,不知道大家看出来没有

运行截图:

在这里插入图片描述

纳尼,直接崩掉了,这是怎么回事呢,明明代码都没有问题,也没有报错啊,,,简直是不可思议啊!!!
指针居然罢工了,叛逆了,这是怎么回事啊???

于是呢,就开始加断点,一步一步的排查,最后可以确定,问题就出在 自定义的重载构造函数中。

但是左右看又看貌似没有问题,,这是怎么回事呢?

Human::Human(const char *nane, int age) {
	// 如果name为空的话,就赋值“无名字”
	if (!name) {
		name = "无名字";
	}

	// 从堆上分配内存给name		
	this->name = new char[strlen(name)+1];

	strcpy_s(this->name, strlen(name)+1, name);	// 深拷贝
	this->age = age;
}

其实,问题就出在第一个参数中:
我错把 name 写成了 nane;
是不是很难看的出来;
就是这一个小小的错误,编译器就认不出name是谁了,后续的代码就全都错了,编译器就直接崩掉了。

现在我们把他改回来试试:

#include <sstream>
#include "Human.h"

// ***************************************
// Human::Human(const char *nane, int age)
Human::Human(const char *name, int age) {
	// 如果name为空的话,就赋值“无名字”
	if (!name) {
		name = "无名字";
	}

	// 从堆上分配内存给name		
	this->name = new char[strlen(name)+1];

	strcpy_s(this->name, strlen(name)+1, name);	// 深拷贝
	this->age = age;
}

Human::~Human() {
	if (name) {
		delete[] name;
	}
}

std::string Human::description() const {
	std::stringstream ret;

	ret << "姓名:" << name << "\t年龄:" << age;

	return ret.str();
}

运行截图:

在这里插入图片描述

问题完美解决。


总结:
以后不管自己是在做练习好,或者是出去工作也好,一定不能马虎,粗心大意,不然造成的后果是不可忽视的。

C++变量修饰符在机器人开发中的实战应用:const、static、volatile与mutable详解 在C++编程中,变量修饰符是控制数据存储、访问和生命周期的关键语法元素,它们直接影响程序的性能、安全性和可维护性。从原理上讲,const确保数据不可变性,提供编译期优化和安全契约;static定义静态存储期,实现数据持久化;volatile防止编译器优化,用于硬件访问;mutable则在const成员函数中允许修改特定状态。这些修饰符的技术价值在于,它们能帮助开发者精确控制内存模型、实现线程安全并提升执行效率。在机器人开发这一对实时性、可靠性和性能要求极高的应用场景中,正确选用修饰符尤为重要。例如,在ROS 阅读详情

相关推荐

中国银行信息科技岗位笔试

收到笔试只剩四天了,收集的资料,后续会更新

weixin_46050242的博客 4594

error:default argument given for parameter 3 of ‘...’ [-fpermissive]

关于error:default argument given for parameter 3 of ‘...’ [-fpermissive]的解决办法

old__tree的博客 1040

用ST25DV芯片+KiCad快速设计NFC标签天线:参数计算/脚本生成/实测优化全流程

本文详细介绍了使用ST25DV芯片和KiCad工具设计NFC标签天线的全流程,包括参数计算、脚本生成和实测优化。通过解析芯片等效工作原理和设计思路,帮助开发者避开常见陷阱,实现高效、可量产的天线设计。文章还提供了Python计算工具和KiCad自动化脚本,大幅提升设计效率和成功率。

jj890的博客 758

面向对象编程--项目练习2

定义一个或者多个类,来描述以下需求: 定义一个类,来表示某模拟养成游戏中人物: 每个人物,有昵称,年龄,性别,配偶,朋友, 支持的活动有:结婚,离婚,交友,断交,询问昵称,询问性别,询问年龄,简介等。

weixin_54124514的博客 800

CentOS 7 常用命令大全

CentOS中Linux命令

m0_63075763的博客 2018

毕设-YOLOv8-OBB 实现自有数据集缺陷旋转检测全过程记录

这次项目让我深入理解了 YOLOv8-OBB 的原理和使用流程。步骤内容工具数据标注制作倾斜缺陷样本格式转换从 HBB 转换为 OBB模型训练使用 Ultralytics YOLOv8 OBBCLI 命令模型测试推理与结果可视化通过 OBB 模型,我的缺陷检测系统获得了更高的精度和鲁棒性。未来我打算继续优化数据增强方式,比如引入随机旋转、仿射变换等,让模型更适应不同角度的样本。

FJN110的博客 446

C++中函数参数的扩展

1,C++ 可以看成是一种更好的 C 语言,所以 C++ 会考虑 C 的欠缺部分,然后给 与一些补充和扩展,本节课讲述 C++ 对函数参数的非常重要的扩展; 2,函数参数的默认值: 1,C++ 中可以在函数声明时为参数提供一个默认值; 1,也可以在函数声明和定义在一起的时候来提供默认值; 2,作用是当函数调用时没有提供参数的值,则使用默认值; 3,int mul(int x = 0)...

weixin_45032957的博客 419

HTML5+CSS3+JS小实例:焦点图波浪切换动画特效

实例:焦点图波浪切换动画特效。字体图标库:Font Awesome。技术栈:HTML+CSS+JS。

艾恩小灰灰的博客 907

C++中的指针类型与构造函数,析构函数

1. 指针类型的作用 1.1 指针取出字节 任何类型的指针占用的空间大小都是相同的 (32位CPU是4字节;64位CPU是8字节) 既然任何类型的指针占用的空间大小都是相同的,为什么指针还需要类型呢? 指针只是指向了一个内存地址,但是当存内存中取值的时候,系统不知道你要从当前指针指向的地址,取几个字节,指定了指针的类型后,系统就知道取几个字节了。 char类型取1个字节,short类型取2个字节,int类型去4个字节。 int main() { int i = 123456

chumingqian的博客 4617

AXI总线详解完结篇

经过几个月的整理和发文,AXI总线详解系列正式迎来最终篇,内容基本涵盖了上一篇文章的全部内容。 所有文章的链接如下: 1、 AXI总线详解 2、AXI总线详解-总线和接口以及协议 3、AXI协议中的通道结构 4、AXI总线详解-AXI4读写操作时序及AXI4猝发地址及选择 5、AXI4交换机制 6、ZYNQ中DMA与AXI4总线-DMA简介 7、AXI总线详解-不同类型的DMA 8、AXI总线详解-DMA内部寄存器的读写方式 9、AXI总线详解-几种应用DMA的场合 10、Altera Scatter-G.

OpenFPGA的博客 5492

Unity小游戏接入抖音敏感词检测

摘要: 本文介绍了Unity小游戏接入抖音敏感词检测的方法。抖音官方提供了两种API:SensitiveWordCheck用于检测敏感词,ReplaceSensitiveWords用于替换敏感词。此外,若使用键盘输入事件,可通过tt.onKeyboardComplete监听回调,平台会自动屏蔽敏感词(替换为*)。接入官方字库可有效避免审核驳回,适用于小游戏中的用户输入功能(如起名系统)。附官方文档链接及参数说明。

类人_猿的博客 4594

C++ 构造函数与对象指针

内含知识点包括: 构造函数 对象指针 公用对象的保护(const) 食用愉快~

qq_63533526的博客 4345

WPF实战项目十七(客户端):数据等待加载弹框动画

1、在Common文件夹下新建文件夹Events,新建扩展类UpdateLoadingEvent。2、新建一个静态扩展类DialogExtensions来编写注册和推送等待消息弹框方法。3、在ViewModel中添加实现类NavigationViewModel。5、在View文件夹下新建用户控件ProgressView.xmal。4、在主窗体MainView.xmal中给弹窗界面命名。6、在MainView.xmal.cs中注册消息。

yigu4011的博客 2347

C++开发精髓语法特性与高效编程实践

管理员紧急断电前的最后3.1415秒,迭戈在断路器间看到无数重影——那些未被delete的指针正化作银色的蛾,啃食父亲未完成的静态成员变量。此刻编译器的报错突然显形为实体:一团具象化的红光在服务器笼中游走,将他的异常指针逐个具现为燃烧的抽象类图。空转的核风扇在头顶发出蜂鸣,仿佛在嘲笑他家族七代程序员都未能逃脱的厄运:他们注定要用C++代码复现一座城,却总在填充完最后一个类成员后,发现所有对象都变成了幽灵的反祖突变体。这不是普通的世界重启——对他而言,这不过是另一个被诅咒的子程序陷入死循环的清晨。

ZWyjDfFo的博客 372

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

c++面向对象编程之继承

今天看了继承这一模块,有点迷迷糊糊,赶快记下来,梳理一下。 c++的类之间有三种继承关系,public,private,protected。对于虚继承,下面也会说明。 例如:class B继承class A 如果B是public继承,则B从A中继承的成员保持着A中的访问权限 如果B是private继承,则B从A中继承的成员(public,protected,private)全变为pri

daisyZH的专栏 471

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

嵌入式开发中的自动化复位陷阱:Keil5配置背后的工程哲学

本文探讨了Keil5在嵌入式开发中的自动化复位机制,特别是'Reset and Run'配置在版本迭代后的行为变化及其背后的工程哲学。分析了Keil5版本更新导致的配置兼容性问题,并提供了系统化的故障排除方法和持续集成环境中的适配策略,帮助开发者构建稳定可靠的开发环境。

lll78的博客 1093

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

如何加速芯片初始化?F407 底层优化技巧

本文深入剖析STM32F407启动流程,通过绕过HAL库、优化内存初始化、精简时钟配置和启用Flash加速,将启动时间从40ms缩短至5ms以内。重点讲解寄存器级操作、启动文件重构与实战测量方法,适用于对响应速度敏感的嵌入式系统。

berry的博客 712

EXACT-MPPI:基于精确ESDF的无训练局部导航方法

带符号距离场(SDF)是机器人感知与规划中表征空间几何关系的基础数学工具,其精度直接决定避障可靠性;精确带符号距离场(ESDF)进一步要求每个查询点的距离值为毫米级解析解,而非体素插值近似。EXACT-MPPI以此为核心,融合模型预测路径积分(MPPI)控制框架,构建了一条从原始点云直达实时控制指令的确定性闭环——无需神经网络、不依赖标注数据、不进行端到端拟合。该方法在动态未知环境中提供可证伪、可调试、可复现的局部导航能力,特别适用于工业AGV、仓储机器人及具身智能系统等对鲁棒性与部署效率有严苛要求的场景。

weixin_34220179的博客 410

C++默认成员函数之一: 构造函数详解以及this指针

C++中的构造函数以及this指针详解

weixin_68539386的博客 1713

一个将类的构造函数调用识别成函数指针的问题

   在Modern C++ Design第二章第一节,有一个关于定制编译器错误提示的例子:templatebool> struct CompileTimeChecker {    CompileTimeChecker(...);    //一个接受任何参数的构造函数};template struct CompileTimeCheckerfalse> { };//特化false版本 /

jxlczjp77的专栏 1804

c++函数指针 类构造 const static new

c++函数指针 类构造 拷贝构造函数 const static new相关知识点

strange_wind的博客 297

C++之构造函数、初始化列表、this指针与常成员函数

构造函数、初始化列表、this指针,常成员函数

weixin_55530858的博客 1220

C++ 1.2 this指针 构造函数

一、this 指针(节省空间,时间换空间) 对象可以根据属性来区分,为了降低空间复杂度,可以让同类型对象共享一份成员函数。 1.编译器针对设计的类型分三步编译: (1)识别和记录类中的属性(名称、类型、访问限定) (2)识别和记录类中函数的声明 例如:对于以下代码,调用函数funa()时其内部调用func(),func()在funa()后面定义,故显示无法识别func(),除非先声明 void func(); 才可。 #include<iostream> using namespa

m0_56194716的博客 922

C++刨析(this指针,构造,析构函数)

那为什么不可以在参数列表显示this指针呢,因为它是成员函数的第一个隐含的指针形参。在我们创建一个对象,对象去调用类中的函数的时候,有没有想过它是怎么进行修改的,回想我们以前写C语言的时候,如果我们写了一个栈,当需要操作栈中的数据时,我们需要把构造出来栈的变量的地址传过去,让函数拿到这个地址来对我们的栈进行出去操作。我们定义了一个对象,这个对象是存在栈帧中的,当我们去调用这个析构函数的时候不是说直接把对象销毁了,对象是在结束的时候由编译器去销毁的,而构造函数只是把对象中所占用的资源归还贵操作系统。

Trustmeican的博客 908

C++中 this指针、构造函数、析构函数

我们定义一个日期类来举例子对于上述类,有这样一个问题,Date类中有Init和Print这两个成员函数,函数体中没有关于不同对象的区分,那d1调用函数的时候,编译器是如和来确定d1而不是d2呢?C++通过引入this指针解决了这种问题。即C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

sqm_C的博客 1479

C++ 构造函数与this指针

之前一直理解的构造函数的参数里没有this指针,因为此时对象还没生成,其他非static成员函数才有this指针,因为当它们被调用时对象已经生成了。然而这样理解是错误的,构造函数参数里也是有this指针的,但这个this指针只是指向了一个内存地址,这个内存地址还并不代表一个类对象,当构造函数完成后,这个地址有足够的信息后才表示这是一个类对象。 在 new 那行添加断点,如: 从这里应该可以看出,在构造函数之前,this指针已经分配了,指向的内存为0x602010,那我们可以看下这个内存里有什么,如: 此

tianyexing2008的博客 4507
上一篇: C++ 算术运算符 - 重载
下一篇: C++ 关系运算符重载与赋值运算符重载
cpp_learners
博客等级 码龄7年 1526粉丝 274原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

cpp_learners

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

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

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

打赏作者

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

抵扣说明:

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

余额充值