C++中vector和數(shù)組之間的轉(zhuǎn)換及其效率問題詳解
因?yàn)橐恍┰?,本人遇到需要頻繁把vector與數(shù)組之間轉(zhuǎn)換的情況,于是就分析了一下兩個(gè)之間轉(zhuǎn)換的實(shí)施以及相關(guān)的效率問題。
數(shù)組轉(zhuǎn)換為vector
眾所周知,一維vector中的元素存儲是順序連續(xù)的,所以我們可以通過訪問第一個(gè)元素的地址以及元素的數(shù)量來訪問一系列的元素。因此,我們可以采取如下操作來對vector進(jìn)行訪問和轉(zhuǎn)換:
先創(chuàng)造一個(gè)數(shù)組
int array_size = 1000;
double **array = (double **)malloc(sizeof(double *) * array_size);
for (int i = 0; i < array_size; i++)
array[i] = (double *)malloc(sizeof(double) * array_size);
for (int i = 0; i < array_size; i++)
for (int j = 0; j < array_size; j++)
array[i][j] = i * array_size + j;
method1
// method1
vector<vector<double>> t(array_size, vector<double>(array_size));
for (int i = 0; i < array_size; i++)
{
// 直接定義一個(gè)一維的vector,其首地址為數(shù)組的起始地址,末尾地址為最后的地址。
t[i] = vector<double>(array[i], array[i] + array_size);
}
method2
// method2
vector<vector<double>> tt(array_size, vector<double>(array_size));
for (int i = 0; i < array_size; i++)
{
// 直接復(fù)制每一個(gè)值
for (int j = 0; j < array_size; j++)
tt[i][j] = array[i][j];
}
method3
vector<vector<double>> ttt(array_size, vector<double>(array_size));
for (int i = 0; i < array_size; i++)
{
// 直接使用memcpy進(jìn)行復(fù)制
memcpy(&ttt[i][0], &array[i][0], array_size * sizeof(double));
}
對于上述的三種方法,我簡單的對其進(jìn)行了效率測試,測試思路是每個(gè)都循環(huán)執(zhí)行100遍,看每個(gè)方法所需要的時(shí)間,測試代碼如下:
clock_t begin, end;
double cost;
begin = clock();
for (int x = 0; x < 100; x++)
{
vector<vector<double>> t(array_size, vector<double>(array_size));
for (int i = 0; i < array_size; i++)
{
t[i] = vector<double>(array[i], array[i] + array_size);
}
}
end = clock();
cost = (double)(end - begin) / CLOCKS_PER_SEC;
printf("method 1 cost: %lf secs\n", cost);
// method2
begin = clock();
for (int x = 0; x < 100; x++)
{
vector<vector<double>> tt(array_size, vector<double>(array_size));
for (int i = 0; i < array_size; i++)
{
for (int j = 0; j < array_size; j++)
tt[i][j] = array[i][j];
}
}
end = clock();
cost = (double)(end - begin) / CLOCKS_PER_SEC;
printf("method 2 cost: %lf secs\n", cost);
// method3
begin = clock();
for (int x = 0; x < 100; x++)
{
vector<vector<double>> ttt(array_size, vector<double>(array_size));
for (int i = 0; i < array_size; i++)
{
memcpy(&ttt[i][0], &array[i][0], array_size * sizeof(double));
}
}
end = clock();
cost = (double)(end - begin) / CLOCKS_PER_SEC;
printf("method 3 cost: %lf secs\n", cost);
多次測試結(jié)果基本情況如下:
method 1 cost: 0.388440 secs
method 2 cost: 0.726254 secs
method 3 cost: 0.371002 secs
由此可見,第三種方法是最快的,不過和第一種方法差距不大,第二種方法是最差的,所需時(shí)間基本是其他兩種方法的兩倍。
vector轉(zhuǎn)換為數(shù)組
和數(shù)組轉(zhuǎn)換為vector的思路基本一致,因?yàn)橐痪S的數(shù)組的存儲也是連續(xù)隨機(jī)存儲的。
先創(chuàng)造一個(gè)vector:
int array_size = 1000;
vector<vector<double>> v(array_size, vector<double>(array_size, 0));
for (int i = 0; i < array_size; i++)
{
for (int j = 0; j < array_size; j++)
{
v[i][j] = i * array_size + j;
}
}
method1
double **array1 = (double **)malloc(sizeof(double *) * array_size);
// method1 因?yàn)関ector存儲是順序且連續(xù)的,所以可以直接把指向數(shù)組每行首地址的地址指向vector每行的首地址
// 上面那句話有點(diǎn)繞,解釋在最后
for (int i = 0; i < array_size; i++)
{
array1[i] = &v[i][0];
}
method2
double **array2 = (double **)malloc(sizeof(double *) * array_size);
// method2 直接復(fù)制每一個(gè)值
for (int i = 0; i < array_size; i++)
{
array2[i] = (double *)malloc(sizeof(double) * array_size);
for (int j = 0; j < array_size; j++)
{
array2[i][j] = v[i][j];
}
}
method3
double **array = (double **)malloc(sizeof(double *) * array_size);
for (int i = 0; i < array_size; i++)
{
// method3 使用memcpy來拷貝數(shù)組的元素
array[i] = (double *)malloc(sizeof(double) * array_size);
memcpy(array[i], &v[i][0], sizeof(double) * array_size);
}
效率測試:因?yàn)槊總€(gè)方法的執(zhí)行都是動(dòng)態(tài)申請內(nèi)存,而作為程序員一定要關(guān)注內(nèi)存,所以每次malloc使用完之后需要free,但是如果按照最開始的方法,在同一個(gè)程序內(nèi)每個(gè)執(zhí)行100遍來測試時(shí)間的話,可能會導(dǎo)致因?yàn)槌绦驁?zhí)行到最后因?yàn)閮?nèi)存使用快滿了而導(dǎo)致速度遍慢,于是,我們每個(gè)方法只是執(zhí)行1遍(因?yàn)?遍的內(nèi)存比較小),然后比較時(shí)間。
測試代碼(注意,這里沒有free,在正式使用的時(shí)候要記得free):
clock_t begin, end;
double cost;
// method1
begin = clock();
double **array1 = (double **)malloc(sizeof(double *) * array_size);
for (int i = 0; i < array_size; i++)
{
array1[i] = &v[i][0];
}
end = clock();
cost += (double)(end - begin) / CLOCKS_PER_SEC;
printf("method 1 cost: %lf secs\n", cost);
// method2
begin = clock();
double **array2 = (double **)malloc(sizeof(double *) * array_size);
for (int i = 0; i < array_size; i++)
{
array2[i] = (double *)malloc(sizeof(double) * array_size);
for (int j = 0; j < array_size; j++)
{
array2[i][j] = v[i][j];
}
}
end = clock();
cost = (double)(end - begin) / CLOCKS_PER_SEC;
printf("method 2 cost: %lf secs\n", cost);
// method3
begin = clock();
double **array3 = (double **)malloc(sizeof(double *) * array_size);
for (int i = 0; i < array_size; i++)
{
array3[i] = (double *)malloc(sizeof(double) * array_size);
memcpy(array3[i], &v[i][0], sizeof(double) * array_size);
}
end = clock();
cost = (double)(end - begin) / CLOCKS_PER_SEC;
printf("method 3 cost: %lf secs\n", cost);
多次測試結(jié)果大致如下:
method 1 cost: 0.000006 secs
method 2 cost: 0.007973 secs
method 3 cost: 0.003540 secs
由此可見第一種方法的速度最快,而且遠(yuǎn)遠(yuǎn)塊于其他兩種方法,第二種方法是第三種方法時(shí)間的兩倍。
結(jié)論,直接賦值指針?biāo)俣?gt;使用memcpy>挨個(gè)賦值。
指針與數(shù)組
我們可以看到在上面vector轉(zhuǎn)化為數(shù)組的中,第一種方法比其他快很多,其具體是怎么實(shí)現(xiàn)的呢,解釋如下:
二維數(shù)組的聲明
二維數(shù)組的聲明有幾種方法,下面介紹其中的一種方法:
// 聲明一個(gè)指向指針的指針,有array_size個(gè)這樣的指針。
double **array = (double **)malloc(sizeof(double *) * array_size);
// 每個(gè)指向指針的指針指向一個(gè)一維數(shù)組的首地址,其一維數(shù)組的長度為array_size。
for (int i = 0; i < array_size; i++)
array[i] = (double *)malloc(sizeof(double) * array_size);

如上圖所示,array是指向指針的指針,其內(nèi)容為array[0]的地址,而array[0]的內(nèi)容為array[0][0]的地址,array[0][0]的內(nèi)容即為每個(gè)元素的值。
第一種方法的解釋
我們首先聲明一個(gè)指向指針的指針,其長度為array_size,也就是說,有array_size個(gè)指針。
然后每個(gè)指針將其內(nèi)容改為每行vector的首地址,這樣就可以訪問每個(gè)元素了。
總結(jié)
到此這篇關(guān)于C++中vector和數(shù)組之間的轉(zhuǎn)換及其效率問題的文章就介紹到這了,更多相關(guān)C++中vector和數(shù)組轉(zhuǎn)換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)CreatThread函數(shù)主線程與工作線程交互的方法
這篇文章主要介紹了C++實(shí)現(xiàn)CreatThread函數(shù)主線程與工作線程交互的方法,是Windows應(yīng)用程序設(shè)計(jì)中非常實(shí)用的方法,需要的朋友可以參考下2014-10-10
C/C++?Qt?TableDelegate?自定義代理組件使用詳解
TableDelegate自定義代理組件的主要作用是對原有表格進(jìn)行調(diào)整,本文主要介紹了QT中TableDelegate?自定義代理組件的使用教程,感興趣的朋友可以了解一下2021-12-12
C++實(shí)現(xiàn)LeetCode(138.拷貝帶有隨機(jī)指針的鏈表)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(138.拷貝帶有隨機(jī)指針的鏈表),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
VSCode插件開發(fā)全攻略之package.json詳解
這篇文章主要介紹了VSCode插件開發(fā)全攻略之package.json的相關(guān)知識,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05
QTimer與QTime實(shí)現(xiàn)電子時(shí)鐘
這篇文章主要為大家詳細(xì)介紹了QTimer與QTime實(shí)現(xiàn)電子時(shí)鐘,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07

