zoukankan      html  css  js  c++  java
  • c++入门之类与内存

    类作为c++编程的核心,自然我们十分关注其内存分配问题。

    这里的这个主题中,我们关注了静态成员,new,delete.还有构造函数和析构函数。

    先上代码:

     1 # include "iostream"
     2 # ifndef STRNGBAD_H_
     3 # define STRNGBAD_H_
     4 class StringBad
     5 {
     6 private:
     7     char *str;
     8     int len;
     9     static int num_strings; //= 0;//可见除了const 量之外,类内部成员是不能在内部赋初值的
    10 public:
    11     StringBad(const char * s);
    12     StringBad();
    13     ~StringBad();
    14 
    15     friend std::ostream & operator<<(std::ostream & os, const StringBad & st);
    16 };
    17 # endif

    这个类声明十分的简洁,我们可以看到,其只有三个成员变量,成员函数也只要构造函数和析构函数,再包含一个友元函数(我们再次强调:友元函数虽然声明在public中,但并不包含在类作用域中)关注一下第 9 行,这里声明了一个静态变量。关于静态变量。需要知道:静态变量只提供一个副本,实际上在内存中只占用一个空间,即就算我们申请了10个StringBad对象,这10个对象本质上会共享1个num_strings变量。

    再来看,这个类的定义函数:

    # include "cstring"
    # include "strngbad.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
    ";
    }
    
    StringBad::StringBad()
    {
        len = 4;
        str = new char[4];
        std::strcpy(str, "C++");
        num_strings++;
        cout << num_strings << ": "" << str << "" default created
    ";
    }
    
    StringBad::~StringBad()
    {
        cout << """ << str << "" object created. ";
        --num_strings;
        cout << num_strings << "left
    ";
        delete[] str;
    }
    
    std::ostream & operator<<(std::ostream & os, const StringBad & st)
    {
        os << st.str;//注意这里打印的是 str,如果不加str呢
        return os;
    }

    我们可以从这个类定义中中,看到静态变量num_strings的作用:统计声明当前作用域中,类对象的个数,当对象产生和销毁的时候,对其动态跟踪。同时,我们注意到:

    这个程序使用的c字符串的痕迹很明显(要逐渐体会c风格字符串有何缺陷)。

    构造函数中使用了new来动态分配内存,析构函数中使用了delete来释放内存。(要注意new和delete的兼容性,即new使用new[],则delete也应使用delete[])。

    下面给出调用该类的代码:

     1 # include "iostream"
     2 using std::cout;
     3 # include "strngbad.h"
     4 
     5 void callme1(StringBad &);
     6 void callme2(StringBad);
     7 
     8 int main()
     9 {
    10     using std::endl;
    11     {
    12         cout << "Starting an inner block.
    ";
    13         StringBad headline1("hello world!");
    14         StringBad headline2("learning forever!");
    15         StringBad sports("i love trvaling!");
    16         cout << "headline1" << headline1 << endl;
    17         cout << "headline12"<< headline2 << endl;
    18         cout << "sports" << sports << endl;
    19         callme1(headline1);
    20         cout << "headline1" << headline1 << endl;
    21         callme2(headline2);
    22         cout << "headline2" << headline2 << endl;
    23         cout << "Initialize one object to another:
    ";
    24         StringBad sailor = sports;
    25         cout << "sailor: " << sailor << endl;
    26     }
    27     cout << "End of main()
    ";
    28     system("pause");
    29     return 0;
    30 }
    31 
    32 void callme1(StringBad & rsb)
    33 {
    34     cout << "String passed by reference:
    ";
    35     cout << "     
    " << rsb << ""
    ";
    36 }
    37 
    38 void callme2(StringBad  sb)
    39 {
    40     cout << "String passed by rvalue:
    ";
    41     cout << "     
    " << sb << ""
    ";
    42 }

    这里先讨论32行和38行:将对象值作为形参和 对象引用作为形参,到底有何区别?

    首先需要明白:当采用按值传递参数的时候,会首先复制原来的类对象,当然,也不是简单的复制。这个复制过程很特殊。比如,我们将这个临时变量定义为A,则将对象B的值传递给函数的时候。过程是:A = B, 更具体的讲,是:A =StringBad(B),这个会发生什么呢,当然是,首先调用构造函数,但很可惜的是,这里的构造函数不是我们定义的构造函数,而是编译器生成的构造函数,因此也没有new这一过程,但是当函数执行完。(意味着函数作用域结束),则意味着要调用析构函数了,而这个析构函数却是我们自己的析构函数。,这是极其容易出错的!!!!

  • 相关阅读:
    HDU1720 A+B Coming
    HDU1390 ZOJ1383 Binary Numbers
    HDU1390 ZOJ1383 Binary Numbers
    HDU2504 又见GCD
    HDU2504 又见GCD
    HDU1335 POJ1546 UVA389 UVALive5306 ZOJ1334 Basically Speaking
    HDU1335 POJ1546 UVA389 UVALive5306 ZOJ1334 Basically Speaking
    HDU1020 ZOJ2478 Encoding
    HDU1020 ZOJ2478 Encoding
    HDU2097 Sky数
  • 原文地址:https://www.cnblogs.com/shaonianpi/p/9955192.html
Copyright © 2011-2022 走看看