千家信息网

C++构造函数常见的坑有哪些

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,今天就跟大家聊聊有关C++构造函数常见的坑有哪些,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。某一天我们接到了一个需求,需要开发一个类似于ST
千家信息网最后更新 2026年11月04日C++构造函数常见的坑有哪些

今天就跟大家聊聊有关C++构造函数常见的坑有哪些,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

某一天我们接到了一个需求,需要开发一个类似于STL中string的类。

我们很快写好了代码:

#include #ifndef STRINGBAD_H_#define STRINGBAD_H_class StringBad {    private:     char *str;     int len;     static int num_strings;    public:     StringBad(const char* s);     StringBad();     ~StringBad();     friend std::ostream & operator << (std::ostream &os, const StringBad & st);};#endif

在这个.h文件当中,我们定义了一个StringBad类,这是C++ Primer当中的一个例子。为什么叫StringBad呢,主要是为了提示,表示这是一个没有完全开发好的demo。

这里有一个小细节,我们在类当中定义的是一个char *也就是字符型指针,而非字符型数组。这意味着我们在类声明当中没有为字符串本身分配空间,而是在构造函数当中使用new来完成的,避免了预先定义字符串的长度。

其次num_strings是一个静态成员,也就是说无论创建了多少对象,它都只会保存一份。类的所有成员共享同一个静态变量。

接下来我们来看一下它的实现:

#include #include "stringbad.h"using std::cout;int StringBad::num_strings = 0;StringBad::StringBad(const char* s) {    len = std::strlen(s);    str = new char[len+1];    std::strcpy(str, s);    num_strings++;    cout << num_strings << ": \"" << str << "\" object created \n";}StringBad::StringBad() {    len = 4;    str = new char[4];    std::strcpy(str, "C++");    num_strings++;    cout << num_strings << ": \"" << str << "\" object created \n";}StringBad::~StringBad() {    cout << "\"" << str << "\" object deleted, ";    --num_strings;    cout << num_strings << " left \n";    delete []str;}std::ostream & operator<<(std::ostream & os, const StringBad &st) {    os << st.str;    return os;}

首先,我们可以注意到第一句就是将num_strings初始化成了0,我们不能在类声明中初始化静态成员变量。因为声明只是描述了如何分配内存,但并不真的分配内存。

所以对于静态类成员,我们可以在类声明之外使用单独的语句进行初始化。因为静态成员变量是单独存储的,并不是对象的一部分。

初始化要在方法文件也就是cpp文件当中,而不是头文件中。因为头文件可能会被引入多次,如果在头文件中初始化将会引起错误。当然也有一种例外,就是加上了const关键字。

从逻辑上看,我们这样实现并没有任何问题,但是当我们执行的时候,就会发现问题很多……

假设我们现在有一个函数:

void callme(StringBad sb) { cout << "    \"" << sb << "\"\n";}

然后我们这么使用:

int main() { StringBad sb("test"); callme(sb); return 0;}

会得到一个奇怪的结果:

从屏幕可以看到我们的析构函数执行了两次,一次很好理解应该是main函数退出的时候自动执行的,还有一次呢?是什么时候执行的?

答案是执行callme函数的时候执行的,因为callme函数使用了值传递。当callme函数执行结束时,也会调用参数sb的析构函数。

如果我们改成引用传递,就一切正常了:

void callme(StringBad &sb) { cout << "    \"" << sb << "\"\n";}int main() { StringBad sb("test"); callme(sb); return 0;}

这还没完,我们把代码再改一下,会发现还有问题:

int main() { StringBad sb("test"); StringBad sports("Spinach Leaves Bowl for Dollars"); StringBad sailor = sports; StringBad knot; StringBad st = sb; return 0;}

执行一下,得到:

会发现又有负数出现了,这是为什么呢?

因为我们执行了StringBad st = sb这样的操作,这个操作并不会调用我们实现的任何一个构造函数。

它等价于:

StringBad st = StringBad(sb);

对应的构造函数原型是:

StringBad(const StringBad&);

当我们用一个对象来初始化另外一个对象的时候,编译器将会自动生成上述的构造函数。这样的构造函数叫做拷贝构造函数,由于我们没有重载拷贝构造函数,因此它不知道要对num_strings变量做处理,也就导致了不一致的发生。

看完上述内容,你们对C++构造函数常见的坑有哪些有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。

函数 文件 成员 时候 静态 C++ 变量 字符 对象 也就是 内容 这是 问题 分配 常见 字符型 代码 内存 字符串 就是 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网与科技 哈尔滨大商圈互联网科技有限公司 互联网是第几次科技革命的成果 科技平台互联网 科技信息互联网 科技与互联网发展 互联网科技排名 世界互联网领先科技成果 九亚互联网科技 电子科技大学互联网 互联网科技博客 联恩商钥互联网科技有限公司 互联网科技公司招聘 银川新华互联网科技职业技术培训学校图片 互联网对科技的发展 移动互联网年度科技创新 洛阳昕诺飞互联网科技有限公司 皮皮虾互联网科技有限公司 长沙渺峰互联网科技有限公司 陕西彩京云互联网科技有限公司 港股互联网科技股 互联网科技公司名称 宁夏科技产业互联网案例 智腾互联网科技有限公司 长沙茂晟互联网科技有限公司 梅州GM互联网络科技有限公司 珠海东科互联网科技有限公司 互联网科技职业技能培训学校 互联网时代高科技布局 互联网科技的前景
0