c++primer第十二章讀書筆記

本章主要講解new運算符在各種情況下的使用注意事項。
c++使用new和delete運算符來動態控制內存。

一、關於靜態成員

(1)靜態成員屬於類,不屬於對象,即在多個對象中只有一個靜態成員對象副本。
(2)靜態數據成員在類中聲明,在包含類方法的文件中初始化。但如果靜態成員是const整型類型或者枚舉類型,則可以在類聲明中初始化。
(3)靜態成員函數由於沒有this指針,因此只能訪問靜態成員。對象要通過作用域限定符來調用靜態成員方法。

在自定義類String要考慮淺拷貝與深拷貝的問題,下面對自定義類中默認方法做個分析,要對函數做深拷貝和淺拷貝的考慮。
二、關於自定義類默認生成的函數
默認構造函數、默認析構函數、拷貝構造函數、賦值運算符、地址運算符

(1)默認構造函數:
帶參數的構造函數也可以是默認構造函數,只要所有的參數都有默認值。
在構造函數中使用new分配內存,必須在相應的析構函數中使用delete來釋放內存。

(2)拷貝構造函數
拷貝函數調用的三種情況。

  1. 新建一個對象並初始化化同類現有對象時,會調用拷貝構造函數。
String s1(s2);
String s1 = s2;
String s1 = String(s2);
String *p2 = new String(s2);
  1. 當函數按值傳遞時,會調用拷貝函數
  2. 返回局部對象時,會調用拷貝構造函數。

由於按值傳遞都將調用拷貝構造函數,因此應該按照引用來傳遞,提高效率。
默認拷貝構造函數逐個複製數據成員,複製的是成員的值,這樣就會造成淺拷貝。
淺拷貝的指的是有複製數據成員指針的值,但沒有爲分配空間,造成兩個指針指向同一塊內存,使得析構函數
對這塊內存釋放了兩次,因此對拷貝構造函數進行重載。

(3)賦值運算符

String s1 = s2;

關於這句代碼可能有兩種使用步驟:
一是初始化,直接調用拷貝構造函數。二是先調用拷貝構造函數,然後使用賦值運算符。

在自定義類型String中,關於賦值運算符要實現深拷貝。

三、在構造函數中使用new的注意事項:

1- 如果構造函數使用new來初始化指針成員,則應該在析構函數中使用delete
2- new對於delete ,new [ ] 對應delete [ ]
3- 多個構造函數中必須使用相同的方式使用new,但可以在一個構造函數中使用new,在另一個構造函數中將指針成員置空(c++新的特性使用nullptr表示空指針)

四、有關返回對象的說明

(1)返回指向const對象的引用,(不會調用拷貝構造函數)旨在提高效率。
(2)返回指向非const對象的引用,這裏主要考慮對流運算符的重載(<< 或者 >>).
(3)返回對象,不能返回局部的引用。
(4)返回const對象,防止在if判斷中將==寫成=,改變對象的值,保護數據。

五、析構函數調用的情況
(1)對象是動態,執行完定義該對象的程序是,將調用對象的析構函數。
(2)如果對象時靜態(外部、靜態(外部)或者來着名稱空間),程序解釋時,調用析構函數
(3)如果對象時new創建的,顯式調用delete刪除對象,將調用析構函數,否則該對象的析構函數不會被調用。

六、關於placement new 運算符
palacement new
在已有的內存上分配空間,不分配空間,只是構造函數的調用。

void * operator new(size_t size,void *p)
{
     return p;
}

cahr buffer[1024]
Test *p2 = new(buffer) Test(200);//operator new(sizo_t ,void *p)
cout << p2->n_ <<endl;//placement new 不分配內存 + 構造函數。

自定義類String
String.h

#ifndef _String_H_
#define _String_H_

#include <iostream>
using namespace std;

class String
{
public:
    String(const char *s);
    String(const String &s);
    String &operator=(const String &s);
    String &operator=(const char *s);
    String();
    ~String();
    char & operator[](int i);
    const char & operator[](int i) const;

    friend bool operator<(const String &s1,const String &s2);
    friend bool operator>(const String &s1,const String &s2);
    friend bool operator==(const String &s1,const String &s2);
    friend ostream &operator<<(ostream &out,const String &st);
    friend istream &operator>>(istream &in,String &st);

    static int HowMany();
private:
    char *str;
    int len;
    static int num_strings; 
    static const int MAXSIZE = 80;
};

#endif //_STRING_H_

String.cpp

#include <iostream>
#include <cstring>
#include "StringBad.h"

using namespace std;

int String::num_strings = 0;

String::String(const char *s)
{
    len = strlen(s);
    str = new char[len + 1];
    strcpy(str,s);
    num_strings++;
//  cout << num_strings << ":" << str << "\"object created " << endl;

}
String::String(const String &s)
{
    num_strings++;
    len = s.len;
    str = new char[len + 1];
    strcpy(str,s.str);
//  cout <<num_strings << ": \"" << str << "\" object created" << endl;
}

String & String::operator=(const String & s)
{
//  cout << "operator = " << endl;
    if(this == &s)
    {
        return *this;
    }
    delete [] str;
    len = s.len;
    str = new char[len + 1];
    strcpy(str,s.str);
    return *this;
}
String & String::operator=(const char *s)
{
    delete [] str;
    len = strlen(s);
    str = new char[len + 1];
    strcpy(str,s);
    return *this;
}

String::String()
{
    len = 4;
    str = new char[1];
    str[0] = '\0';
    num_strings++;
//  cout << num_strings << ":" << str << "\"default object created" << endl; 
}

String::~String()
{
//  cout << "\"" << str << "\"object deleted, ";
    --num_strings;
//  cout << num_strings << endl;
    delete [] str;
}

bool operator<(const String &s1,const String &s2)
{
    return strcmp(s1.str,s2.str) < 0;
}

bool operator>(const String &s1,const String &s2)
{
    return s2 < s1;
}
bool operator==(const String &s1,const String &s2)
{
    return strcmp(s1.str,s2.str) == 0;
}

char & String::operator[](int i)
{
    return str[i];
}
const char & String::operator[](int i) const
{
    return str[i];
}

ostream & operator<<(ostream &out,const String &st)
{
    out << st.str;
    return out;
}

istream &operator>>(istream &in,String &st)
{
    char temp[80];
    in.get(temp,80);
    if(in)
    {
        st = temp; // operator=(const char *);
    }
    while(in && in.get() != '\n')
        continue;
    return in;
}

int String::HowMany()
{
    return num_strings;
}

main.cpp

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

using namespace std;

void callme1(String &);
void callme2(String );
int main()
{
    String name;
    cin >> name;
    cout << name << endl;

    return 0;
}


void callme1(String &rsb )
{
    cout << "callme1 " << endl;

}

void callme2(String rsb)
{
    cout << "callem2" << endl;
}

發佈了106 篇原創文章 · 獲贊 18 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章