C++のポインタは本当に早いのか?

更新日:2021年9月21日


MFCとは、完全な機械語に翻訳されるプログラム言語です。ネイティブなプログラム言語として知られている言語のMicrosoftのC++言語です。


Microsoftの言語のC++には、CLRと言うC++がありますが、CLRは、ガベージコレクターを使用している.NetFrameworkを使ってプログラミングする事が出来る言語です。CLRのC++言語の事をマネージなプログラム言語と言います。この為、CLRのC++言語の処理速度は、C#やVBと殆ど同じ処理速度で動作する言語です。なので、このブログては、C#の処理速度をマネージな言語の処理速度とします。つまり、あえて、VBやCLRで処理速度を計測しないと言う事です。



上記、画像は、当社のFreeソフトの「MFC ベンチマーク」を実行して処理速度計測をした結果図です。


このブログで説明する上記、画像のソフトウェアは、Vector株式会社のWebサイトでFreeソフトとしてダウンロードできます。

ダウンロードサイトは、以下の通りです。


https://www.vector.co.jp/soft/winnt/hardware/se522388.html

https://www.vector.co.jp/soft/winnt/hardware/se522389.html


皆さんのパソコンにインストールしてお使い下さい。

どんな処理を書くと早いプログラムになるのか等のご参考になればと思っております。


さて、プログラムの詳細です。


以下の様なプログラムの内容になっています。

m_TextBox15.に、処理回数が入力されています。


void CArrayFastedDlg::OnBnClickedButton1()

{

// int[] newによる動的配列

CString CSDat(L"");

m_TextBox1.SetWindowTextW(CSDat); // クリア

m_TextBox15.GetWindowTextW(CSDat); // 値を取得

std::chrono::system_clock::time_point Start, End;

double Time;

int iLen = _ttoi(CSDat); //CString→intに変換;

int* iDatH = new int[iLen];

Start = std::chrono::system_clock::now();

for (int i = 0; i < iLen; i++) {

iDatH[i] = i;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox1.SetWindowTextW(CSDat); // 表示

delete[] iDatH;

}



void CArrayFastedDlg::OnBnClickedButton2()

{

// vector<int>配列 push_back

CString CSDat(L"");

m_TextBox2.SetWindowTextW(CSDat); // クリア

m_TextBox15.GetWindowTextW(CSDat); // 値を取得

std::chrono::system_clock::time_point Start, End;

double Time;

int iLen = _ttoi(CSDat); //CString→intに変換;

vector<int> ViDatH;

ViDatH.reserve(iLen); // メモリー確保

Start = std::chrono::system_clock::now();

for (int i = 0; i < iLen; i++) {

ViDatH.push_back(i);

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox2.SetWindowTextW(CSDat); // 表示

}



void CArrayFastedDlg::OnBnClickedButton4()

{

// vector<int>配列 push_back

CString CSDat(L"");

m_TextBox4.SetWindowTextW(CSDat); // クリア

m_TextBox15.GetWindowTextW(CSDat); // 値を取得

std::chrono::system_clock::time_point Start, End;

double Time;

int iLen = _ttoi(CSDat); //CString→intに変換;

vector<int> ViDatH;

//ViDatH.reserve(iLen); // メモリー確保

Start = std::chrono::system_clock::now();

for (int i = 0; i < iLen; i++) {

ViDatH.push_back(i);

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox4.SetWindowTextW(CSDat); // 表示

}



void CArrayFastedDlg::OnBnClickedButton3()

{

// vector<int>配列 at()

CString CSDat(L"");

m_TextBox3.SetWindowTextW(CSDat); // クリア

m_TextBox15.GetWindowTextW(CSDat); // 値を取得

std::chrono::system_clock::time_point Start, End;

double Time;

int iLen = _ttoi(CSDat); //CString→intに変換;

vector<int> ViDatH;

ViDatH.reserve(iLen); // メモリー確保

for (int i = 0; i < iLen; i++) {

ViDatH.push_back(0); //初期化

}

Start = std::chrono::system_clock::now();

for (int i = 0; i < iLen; i++) {

ViDatH.at(i) = i;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox3.SetWindowTextW(CSDat); // 表示

}



void CArrayFastedDlg::OnBnClickedButton5()

{

// vector<int>配列 []

CString CSDat(L"");

m_TextBox5.SetWindowTextW(CSDat); // クリア

m_TextBox15.GetWindowTextW(CSDat); // 値を取得

std::chrono::system_clock::time_point Start, End;

double Time;

int iLen = _ttoi(CSDat); //CString→intに変換;

vector<int> ViDatH;

ViDatH.reserve(iLen); // メモリー確保

for (int i = 0; i < iLen; i++) {

ViDatH.push_back(0); //初期化

}

Start = std::chrono::system_clock::now();

for (int i = 0; i < iLen; i++) {

ViDatH[i] = i;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox5.SetWindowTextW(CSDat); // 表示

}



void CArrayFastedDlg::OnBnClickedButton6()

{

// CString[] new 動的配列 ポインタ

CString CSDat(L"");

m_TextBox6.SetWindowTextW(CSDat); // クリア

m_TextBox15.GetWindowTextW(CSDat); // 値を取得

std::chrono::system_clock::time_point Start, End;

double Time;

int iLen = _ttoi(CSDat); //CString→intに変換;

int a = 0;

CString* CSDatH = new CString[iLen];

Start = std::chrono::system_clock::now();

for (CString *CSp = CSDatH; a < iLen; CSp++) {

CSDat.Format(L"%d", a); // int→CStringに変換

*CSp = CSDat;

a += 1;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox6.SetWindowTextW(CSDat); // 表示

delete[] CSDatH;

}



void CArrayFastedDlg::OnBnClickedButton7()

{

// array配列  (mallocで一部をヒープに移動するか、vector等を使用する)

CString CSDat(L"");

m_TextBox7.SetWindowTextW(CSDat); // クリア

std::chrono::system_clock::time_point Start, End;

double Time;

std::array<int, 100000> AiDatH = {};

Start = std::chrono::system_clock::now();

for (int i = 0; i < 100000; i++) {

AiDatH[i] = i;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox7.SetWindowTextW(CSDat); // 表示

}



void CArrayFastedDlg::OnBnClickedButton8()

{

// array配列 初期化した場合 (mallocで一部をヒープに移動するか、vector等を使用する)

CString CSDat(L"");

m_TextBox8.SetWindowTextW(CSDat); // クリア

std::chrono::system_clock::time_point Start, End;

double Time;

int iLen = 100000;

std::array<int, 100000> AiDatH = { 0 };

Start = std::chrono::system_clock::now();

for (int i = 0; i < iLen; i++) {

AiDatH[i] = i;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox8.SetWindowTextW(CSDat); // 表示

}



void CArrayFastedDlg::OnBnClickedButton9()

{

// int[] mallocによる動的配列  

// 動的メモリー確保のmallocで配列を確保する事でコープ領域を使う事が出来る。

// でも落とし穴があるのでvectorを使用する方が良い

CString CSDat(L"");

m_TextBox9.SetWindowTextW(CSDat); // クリア

m_TextBox15.GetWindowTextW(CSDat); // 値を取得

std::chrono::system_clock::time_point Start, End;

double Time;

int iLen = _ttoi(CSDat); // CString→intに変換

int* iDatH;

iDatH = (int*)malloc(sizeof(int) * iLen); // 動的メモリーの確保

Start = std::chrono::system_clock::now();

for (int i = 0; i < iLen; i++) {

iDatH[i] = i;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox9.SetWindowTextW(CSDat); // 表示

//int x = iDatH[9]; // テスト

free(iDatH);

}



void CArrayFastedDlg::OnBnClickedButton10()

{

// CString[] newによる動的配列

CString CSDat(L"");

m_TextBox10.SetWindowTextW(CSDat); // クリア

m_TextBox15.GetWindowTextW(CSDat); // 値を取得

std::chrono::system_clock::time_point Start, End;

double Time;

int iLen = _ttoi(CSDat); //CString→intに変換;

CString* CSDatH = new CString[iLen];

Start = std::chrono::system_clock::now();

for (int i = 0; i < iLen; i++) {

CSDat.Format(L"%d", i); // int→CStringに変換

CSDatH[i] = CSDat;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox10.SetWindowTextW(CSDat); // 表示

delete[] CSDatH;

}



void CArrayFastedDlg::OnBnClickedButton11()

{

// int[] new 動的配列 ポインタ

CString CSDat(L"");

m_TextBox11.SetWindowTextW(CSDat); // クリア

m_TextBox15.GetWindowTextW(CSDat); // 値を取得

std::chrono::system_clock::time_point Start, End;

double Time;

int iLen = _ttoi(CSDat); //CString→intに変換;

int a = 0;

int* iDatH = new int[iLen];

Start = std::chrono::system_clock::now();

for (int* ip = iDatH; a < iLen; ip++) {

*ip = a;

a += 1;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox11.SetWindowTextW(CSDat); // 表示

delete[] iDatH;

}



void CArrayFastedDlg::OnBnClickedButton12()

{

// int[100000] 静的配列

CString CSDat(L"");

m_TextBox12.SetWindowTextW(CSDat); // クリア

std::chrono::system_clock::time_point Start, End;

double Time;

int iDatH[100000];

Start = std::chrono::system_clock::now();

for (int i = 0; i < 100000; i++) {

iDatH[i] = i;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox12.SetWindowTextW(CSDat); // 表示

}



void CArrayFastedDlg::OnBnClickedButton13()

{

// CString[100000] 静的配列

CString CSDat(L"");

m_TextBox13.SetWindowTextW(CSDat); // クリア

std::chrono::system_clock::time_point Start, End;

double Time;

CString CSDatH[100000];

Start = std::chrono::system_clock::now();

for (int i = 0; i < 100000; i++) {

CSDat.Format(L"%d", i); // int→CStringに変換

CSDatH[i] = CSDat;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox13.SetWindowTextW(CSDat); // 表示

}



void CArrayFastedDlg::OnBnClickedButton15()

{

// char[] new 動的配列 ポインタ

CString CSDat(L"");

m_TextBox14.SetWindowTextW(CSDat); // クリア

m_TextBox15.GetWindowTextW(CSDat); // 値を取得

std::chrono::system_clock::time_point Start, End;

double Time;

int iLen = _ttoi(CSDat); //CString→intに変換;

char* chDatH = new char[iLen];

CString* CSDatH = new CString[iLen];

int a = 0;

char* chW;

Start = std::chrono::system_clock::now();

for (char* chp = chDatH; a < iLen; chp++) {

CSDat.Format(L"%d", a); // int→CStringに変換

CStringA CSAData(CSDat);

const char* cchData = CSAData;

chW = const_cast<char*>(cchData); //constを削除するキャスト

chp = chW;

CSDatH[a] = chp;

a++;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox14.SetWindowTextW(CSDat); // 表示

delete[] chDatH;

delete[] CSDatH;

}



void CArrayFastedDlg::OnBnClickedButton16()

{

// char[] new 動的配列

CString CSDat(L"");

m_TextBox16.SetWindowTextW(CSDat); // クリア

m_TextBox15.GetWindowTextW(CSDat); // 値を取得

std::chrono::system_clock::time_point Start, End;

double Time;

int iLen = _ttoi(CSDat); //CString→intに変換;

CString* CSDatH = new CString[iLen];

Start = std::chrono::system_clock::now();

for (int i = 0; i < iLen; i++) {

CSDat.Format(L"%d", i); // int→CStringに変換

CStringA CSAData(CSDat);

const char* cchData = CSAData;

chDat = const_cast<char*>(cchData); //constを削除するキャスト

CSDatH[i] = chDat;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox16.SetWindowTextW(CSDat); // 表示

delete[] CSDatH;

}



void CArrayFastedDlg::OnBnClickedButton17()

{

// string[] new 動的配列

CString CSDat(L"");

m_TextBox17.SetWindowTextW(CSDat); // クリア

m_TextBox15.GetWindowTextW(CSDat); // 値を取得

std::chrono::system_clock::time_point Start, End;

double Time;

int iLen = _ttoi(CSDat); //CString→intに変換;

char* chDat;

string* strDatH = new string[iLen];

Start = std::chrono::system_clock::now();

for (int i = 0; i < iLen; i++) {

CSDat.Format(L"%d", i); // int→CStringに変換

CStringA CSADat(CSDat); //ASCIIに変換

string strDat(CSADat); //stringに変換

strDatH[i] = strDat;

}

End = std::chrono::system_clock::now();

Time = (double)std::chrono::duration_cast<std::chrono::microseconds>(End - Start).count();

Time = Time / 1000;

CSDat.Format(L"%.3f", Time); //Double→CStringに変換 小数点第#位まで表示の場合

CSDat = CSDat + L"ms";

m_TextBox17.SetWindowTextW(CSDat); // 表示

delete[] strDatH;

}


以上が、MFC ベンチマークで使用したプログラムです。


やはり、ポインタは早いと言う結果でした。

しかし、array配列の速さは驚異的早さです。

こんなにも早いとは思ってもいませんでした。


しかし、array配列は、問題が多い様です。

array配列を使わずに、

vector配列を使う事をMicrosoftは推薦しています。

以上、ポインタは本当に早いのか?でした。


2021年9月21日 追記

 突然出ずか、マイクロソフトがプログラム言語の仕様を変更した様です。

今まで早かった、ポインタが異常に遅くなり、計算結果が表示しにくくなり、その上、計算結果がめちゃくちゃになると言う現象が発生する様になりました。


WindowsAPIやマイクロソフト提供のプログラムには、相変わらず、&を使用しているにも拘らず、どうやら、ポインタを使うなと言う仕様変更の様です。


ポインタは、アンセーフコードです。いきな