首页 > 作文

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

更新时间:2023-04-04 09:39:44 阅读: 评论:0

文章转自微信 公众号: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文件当中,我们定义了一个strqq头像 黑白ingbad类,这是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++构造函数的坑内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

本文发布于:2023-04-04 09:39:41,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/a733dfbb68c569651403741b44ead3f9.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:C++构造函数一些常见的坑.doc

本文 PDF 下载地址:C++构造函数一些常见的坑.pdf

标签:函数   初始化   静态   变量
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图