最近発見されたC++のいくつかの「ブラックテクノロジー」

7519 ワード

delete[]のプロファイル順序
まず小さな発見ですが、delete[]の場合、構造順序とは逆の順序で解析されます!(元の構造順とは、new[]の場合、下付き順で構成されていた)
#include 
using namespace std;

class Log
{
public:
    void setId(int id) {
        this->id = id;
    }

    ~Log() {
        cout << "Destruct " << id << endl;
    }

private:
    int id;
};


int main() {
    Log* logs = new Log[4];
    for (int i = 0; i < 4; ++i)
        logs[i].setId(i);

    delete [] logs;

    return 0;
}

上記のコードの出力結果は次のとおりです.
Destruct 3
Destruct 2
Destruct 1
Destruct 0

参照変数のサイズ
コンパイラ内部は「定数ポインタ」で参照されるそうですが、まずその大きさから見てみましょう.
#include 
using namespace std;

class Log
{
public:
    void setId(int id) {
        this->id = id;
    }

    ~Log() {
        cout << "Destruct " << id << endl;
    }

private:
    int id;
};

struct Wrapper
{
    Log& ref;
    Wrapper(Log log)
    : ref(log) {}
};


int main() {
    Log log;
    Wrapper w(log);
    cout << sizeof(w) << ' ' << sizeof(log) << endl;
    return 0;
}

出力結果:8 48はポインタの大きさです!psは、sizeof(ref)によって直接判断することはできない.なぜなら、4 4が出力され、refが参照するオブジェクトのサイズが計算されるからである.
定数ポインタVSポインタ定数
次のトピックでは、ポインタ(タイプの)定数と(指す)定数(の)ポインタを区別する必要があります.左かっこの注釈を見て、はっきりしていると信じていますよね?
まだ分かりませんが、自分の私蔵ノートをpoするしかありません.
定数ポインタは、その名の通り、定数を指すポインタです.たとえば、次のようになります.
const int id = 555;
const int* p1 = &id;
int const* p2 = &id;

*p1 = 233;  //   !             ,        

int hello = 666;
p1 = p2 = &hello;   //          ,        

ポインタで指向する変数の値を変更することはできず、関数のパラメータ伝達時に変数の内容が変更されないことを宣言するのによく使われるのが特徴です(もちろん、通常参照でも構いません).
xx定数とは、この変数が定数であり、値を変更できないことを意味します.したがって、「ポインタ定数」とは、このような形式を指します.
int id = 233, id2 = 555;
int* const p = &id;
id = 666;
p = &id2;//   !p     ,        
p = &id;//   !     ,    p    &id       , ╭(╯^╰)╮

元の変数の内容を変更することができます(const修飾ではない限り)、ポインタの値を変更することはできません.つまり、このポインタはこの変数を指すように指定するしかありません.
コンパイラ内部では定数ポインタで参照を実現しているそうです!(うわさにすぎない)
ポインタ定数で参照をシミュレート!
直接poコード、コードがはっきりしていて、説明する必要はありません^^;
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

class Log
{
public:
    Log(int n)
    : id(n) {}

    Log& operator = (const Log& rhs) {
        id = rhs.id;
        return *this;
    }

    void display() const {
        cout << "Log " << id << endl;
    }

private:
    int id;
};


template
class Reference
{
private:
    /*   “    ”        :
            1)         ;
            2)          ;
            3)                   。

                  ,     ,              !
    */
    T* const pointer;

public:
    Reference(T& object)
    : pointer(&object) {}

    T& operator = (T& object) {
        return *pointer = object;
    }
};


int main() {
    Log test(233);
    test.display();

    Reference ref(test);
    Log test2(666);
    ref = test2;    //            
    test.display();

    return 0;
}

出力結果は次のとおりです.
Log 233
Log 666

未完待機
2016-08-18 15:57に更新
jacketは至善園4号にあります