iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++构造函数一些常见的坑
  • 338
分享到

C++构造函数一些常见的坑

2024-04-02 19:04:59 338人浏览 独家记忆
摘要

文章转自微信 公众号:Coder梁(ID:Coder_LT) 某一天我们接到了一个需求,需要开发一个类似于STL中string的类。 我们很快写好了代码: #include <

文章转自微信 公众号:Coder梁(ID:Coder_LT)

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

我们很快写好了代码:

#include <iOStream>
#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 <cstring>
#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++构造函数的坑内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++构造函数一些常见的坑

本文链接: https://www.lsjlt.com/news/161492.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++构造函数一些常见的坑
    文章转自微信 公众号:Coder梁(ID:Coder_LT) 某一天我们接到了一个需求,需要开发一个类似于STL中string的类。 我们很快写好了代码: #include <...
    99+
    2022-11-12
  • C++构造函数常见的坑有哪些
    今天就跟大家聊聊有关C++构造函数常见的坑有哪些,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。某一天我们接到了一个需求,需要开发一个类似于STL中string的类。我们很快写好了代码...
    99+
    2023-06-22
  • C++踩坑实战之构造和析构函数
    目录前言构造函数 通过构造函数实现的类型转换 派生类的构造函数 析构函数 继承中的析构函数 应用 总结前言 我是练习时长一年的 C++ 个人练习生,喜欢野指针、模板报错和未定义行为(...
    99+
    2022-11-12
  • C++构造函数的一些注意事项总结
    目录1、匿名对象2、拷贝构造函数的调用时机3、深拷贝和浅拷贝总结1、匿名对象 首先应该明确匿名对象,匿名对象是之没有对象名,调用完构造函数后即析构的对象。下面通过代码捕捉类的构造函数...
    99+
    2022-11-12
  • C++11怎么移动构造函数通常
    这篇文章主要讲解了“C++11怎么移动构造函数通常”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++11怎么移动构造函数通常”吧!不会抛出异常的移动构造函数拷贝构造函数通常伴随着内存分配操...
    99+
    2023-06-19
  • 一文带你学习一下C++中的构造函数
    目录C++构造函数学习1.带参数的构造函数2.多个构造函数3.拷贝构造函数C++构造函数学习 构造函数是一种特殊的函数,它用于在创建对象时初始化对象的值。所有的类都有构造函数,但如果...
    99+
    2023-05-19
    C++构造函数的使用 C++构造函数学习 C++构造函数 C++ 函数
  • C++中怎么定义一个构造函数
    C++中怎么定义一个构造函数,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。C++构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后...
    99+
    2023-06-17
  • C++的构造函数和析构函数是什么
    本篇内容主要讲解“C++的构造函数和析构函数是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++的构造函数和析构函数是什么”吧!目录一、构造函数二、C++类的内存模型1、只定义成员函数2、...
    99+
    2023-06-20
  • C++中的构造函数详解
    目录普通变量的初始化构造函数一定会生成默认构造函数吗?防止隐式类型转换赋值与初始化的区别对象的计数成员初始化的顺序类的引用成员构造函数使用注意事项参考总结普通变量的初始化 当我们在定...
    99+
    2022-11-12
  • 正确理解C++的构造函数和析构函数
    目录一、构造函数二、C++类的内存模型2.1、只定义成员函数2.2、往空类中添加静态成员变量2.3、再加入非静态成员变量三、this指针四、析构函数一、构造函数 首先,由于类只是一个...
    99+
    2022-11-12
  • C++分析构造函数与析造函数的特点梳理
    目录构造函数的调用构造函数的分类及调用拷贝构造的调用时机深拷贝与浅拷贝构造函数的调用 默认情况下编译器至少给一个类添加3个函数 1.默认构造函数(无参,函数体实现)--完成对象的初始...
    99+
    2022-11-13
  • C#中的构造函数怎么用
    这篇文章主要介绍了C#中的构造函数怎么用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C#中的构造函数怎么用文章都会有所收获,下面我们一起来看看吧。C# 中的构造函数类的 构造函数 是类的一...
    99+
    2023-06-17
  • C++类继承时的构造函数
    前言: 子类需要编写自己的构造函数和析构函数,需要注意的是,子类只负责对新增的成员进行初始化和扫尾编写构造和析构函数,父类成员的初始化和扫尾工作由父类的构造函数和析构函数完成。 无论...
    99+
    2022-11-13
  • C++浅析构造函数的特性
    目录构造函数的概念构造函数的特性只能有一个构造函数构造函数的概念 构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有一个合适的初始值...
    99+
    2022-11-13
  • C#结构体构造函数的实例分析
    这期内容当中小编将会给大家带来有关C#结构体构造函数的实例分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。C#结构体构造函数的应用是如何的呢?C#结构体构造函数的实例1、  &nbs...
    99+
    2023-06-18
  • C#中构造函数和析构函数的作用是什么
    本篇文章给大家分享的是有关C#中构造函数和析构函数的作用是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。C#构造函数(constructor)包括实例C#构造函数和静态C#...
    99+
    2023-06-17
  • C#中构造函数和析构函数的区别是什么
    这篇文章将为大家详细讲解有关C#中构造函数和析构函数的区别是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。C#构造函数和析构函数在你可以访问一个类的方法、属性或任何其它东西之前, ***...
    99+
    2023-06-18
  • go中make用法及常见的一些坑
    目录make用法和参数用法使用make常见的一些坑1:slice使用make2:map使用map:总结make用法和参数用法 golang分配内存有一个make函数,该函数第一个数类...
    99+
    2022-12-26
    go语言make go语言make
  • C++11移动构造函数的使用
    目录一、引言二、左值和右值三、深拷贝构造函数四、右值引用五、移动构造函数六、std::move()七、参考资料一、引言 移动构造函数是什么?先举个例子,你有一本书,你不想看,但我很想...
    99+
    2022-11-13
  • C++中的复制构造函数详解
    目录复制构造函数复制构造函数的三种调用复制构造函数的禁用深拷贝与浅拷贝一定会生成默认复制构造函数吗?参考 总结普通变量的复制 有时我们会在定义一个变量的同时使用另一个变量来初始化它。...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作