C++ÊÇÒ»ÃÅ×ÔÓɵÄÓïÑÔ£¬ÔÊÐíÄã×ÔÓɵıí´ï×Ô¼ºµÄÒâͼ£¬¶Ô²»¶Ô? ËùÒÔÎÒÃǼÈÈ»¿ÉÒÔnewÒ»¸öһάÊý×飬ҲӦ¸Ã¿ÉÒÔnew³ö¶àάÊý×飬¶Ô²»¶Ô?ÏÈÀ´¿´¿´ÕâÆªÎÄÕ°ɡ£
BoostÔ´Âë±Ê¼Ç£ºboost::multi_array
лÐù /ÎÄ
¶¯»ú
C++ÊÇÒ»ÃÅ×ÔÓɵÄÓïÑÔ£¬ÔÊÐíÄã×ÔÓɵıí´ï×Ô¼ºµÄÒâͼ£¬¶Ô²»¶Ô? ËùÒÔÎÒÃǼÈÈ»¿ÉÒÔnewÒ»¸öһάÊý×飬ҲӦ¸Ã¿ÉÒÔnew³ö¶àάÊý×飬¶Ô²»¶Ô?ÏÈÀ´¿´Ò»¸öÀý×Ó£º
int* pOneDimArr = new int[10]; //н¨Ò»¸ö10¸öÔªËØµÄһάÊý×é
pOneDimArr[0] = 0; //·ÃÎÊ
int** pTwoDimArr = new int[10][20]; //´íÎó£¡
pTwoDimArr[0][0] = 0; //·ÃÎÊ
µ«ÊÇ£¬ºÜ¿Éϧ£¬ÈýËÄÁ½ÐдúÂëµÄÐÐΪ²¢·ÇÈçÄãËùÏëÏóµÄÄÇÑù——ËäÈ»´ÓÓï·¨ÉÏËüÃÇ¿´ÆðÀ´ÊÇÄÇô“×ÔÈ»”¡£
ÕâÀïµÄÎÊÌâÔÚÓÚ£¬new int[10][20]·µ»ØµÄ²¢·Çint**ÀàÐ͵ÄÖ¸Õ룬¶øÊÇint (*)[20]ÀàÐ͵ÄÖ¸Õ루ÕâÖÖÖ¸Õë±»³ÆÎªÐÐÖ¸Õ룬¶ÔËü“+1”Ï൱ÓÚÔÚÊýÖµÉϼÓÉÏÒ»ÐеĴóС£¨±¾ÀýΪ20£©£¬Ò²¾ÍÊÇ˵£¬ÈÃËüÖ¸ÏòÏÂÒ»ÐУ©£¬ËùÒÔÎÒÃǵĴúÂëÓ¦¸ÃÏñÕâÑù£º
int (*pTwoDimArr)[20] = new int[i][20]; //ÕýÈ·
pTwoDimArr[1][2] = 0; //·ÃÎÊ
×¢ÒâpTwoDimArrµÄÀàÐÍ——int(*)[20]ÊǸöºÜÌØÊâµÄÀàÐÍ£¬Ëü²»ÄÜת»¯Îªint**£¬ËäÈ»Á½ÕßË÷ÒýÔªËØµÄÓï·¨ÐÎʽһÑù£¬¶¼ÊÇ“p[i][j]”µÄÐÎʽ£¬µ«ÊÇ·ÃÎÊÄÚ´æµÄ´ÎÊýÈ´²»Ò»Ñù£¬ÓïÒåÒ²²»Ò»Ñù¡£
×î¹Ø¼üµÄÎÊÌ⻹ÊÇ£ºÒÔÉÏÃæÕâÖÖÆÓËØµÄ·½Ê½À´´´½¨¶àάÊý×飬ÓÐÒ»¸ö×î´óµÄÏÞÖÆ£¬¾ÍÊÇ£º³ýÁ˵Úһά£¬ÆäËüάµÄ´óС¶¼±ØÐëÊDZàÒëÆÚÈ·¶¨µÄ¡£ÀýÈ磺
int (*pNdimArr)[N2][N3][N4] = new int[n1][N2][N3][N4];
ÕâÀïN2,N3,N4±ØÐë¶¼ÊDZàÒëÆÚ³£Á¿£¬Ö»ÓÐn1¿ÉÒÔÊDZäÁ¿£¬Õâ¸öÏÞÖÆÓë¶àάÊý×éµÄË÷Òý·½Ê½Óйؗ—ÎÞÂÛ¶àÉÙάµÄÊý×é¶¼ÊÇÏßÐÔ´æ´¢ÔÚÄÚ´æÖеģ¬ËùÒÔ£º
pTwoDimArr[i][j] = 0;
±»±àÒëÆ÷Éú³ÉµÄ´úÂëÀàËÆÓÚ£º
*( (int*)pTwoDimArr+i*20+j ) = 0;
20¾ÍÊǶþάÊý×éµÄÐÐ¿í£¬ÎÊÌâÔÚÓÚ£¬Èç¹ûÔÊÐí¶þάÊý×éµÄÐпíÒ²ÊǶ¯Ì¬µÄ£¬ÕâÀï±àÒëÆ÷¾ÍÎÞ·¨Éú³É´úÂ루20ËùÔڵĵط½Ó¦¸Ã·ÅÊ²Ã´ÄØ£¿£©¡£»ùÓÚÕâ¸öÔÒò£¬C++Ö»ÔÊÐí¶àάÊý×éµÄµÚһάÊǶ¯Ì¬µÄ¡£
²»ÐÒµÄÊÇ£¬ÕýÓÉÓÚÕâ¸öÏÞÖÆ£¬C++ÖеĶàάÊý×é¾ÍÔÚ´ó¶àÊýÇé¿öϱä³ÉÁËÓÐÃûÎÞʵµÄÎÞÓÃÖ®Îï¡£ÎÒÃǾ³£¿ÉÒÔÔÚÂÛ̳ÉÏ¿´µ½¹ØÓÚ¶àάÊý×éµÄÎÊÌ⣬һ°ãÕâÀàÎÊÌâµÄºËÐͼÔÚÓÚ£ºÈçºÎÄ£·ÂÒ»¸ö“ÍêÈ«¶¯Ì¬µÄ”¶àάÊý×é¡£ÕâÀï“ÍêÈ«¶¯Ì¬”µÄÒâ˼ÊÇ£¬ËùÓÐάµÄ´óС¶¼¿ÉÒÔÊǶ¯Ì¬µÄ±äÁ¿£¬¶ø²»½öÊǵÚһά¡£ÂÛ̳Éϸø³öµÄ´ð°¸²»Ò»¶ø×㣬ÓеÄÒѾÏ൱²»´í£¬µ«ÊÇҪôȱ·¦¿ÉÀ©Õ¹ÐÔ£¨¼´À©Õ¹µ½NάµÄÇé¿ö£©£¬ÒªÃ´ÔÚ·ÃÎÊÔªËØµÄÐÎʽÉÏÔ¶Ô¶ÍÑÀëÁËÄÚ½¨µÄ¶àάÊý×éµÄ·ÃÎÊÐÎʽ£¬ÒªÃ´ÏûºÄÁ˹ý¶à¶îÍâµÄ¿Õ¼ä¡£¹é¸ùµ½µ×£¬ÎÒÃÇÐèÒªµÄÊÇÒ»¸öÀàËÆÕâÑùµÄ¶àάÊý×éʵÏÖ£º
//´´½¨Ò»¸öintÐ͵ÄDIMSάÊý×飬dim_sizesÓÃÓÚÖ¸¶¨¸÷άµÄ´óС£¬¼´n1*n2*n3
multi_array<int,DIMS> ma ( dim_sizes[n1][n2][n3] );
ma[i][j][k] = value; //ΪµÚiÒ³jÐÐkÁеÄÔªËØ¸³Öµ
ma[i][j] = value; //±àÒë´í£¡
ma[i] = value; //±àÒë´í£¡
ma[i][j][k][l] = value;//±àÒë´í£¡
ÕâÑùÒ»¸ömulti_array£¬Äܹ»×Ô¶¯¹ÜÀíÄڴ棬ӵÓкÍÄÚ½¨¶àάÊý×éÒ»ÖµĽçÃæ£¬²¢ÇÒ¸÷άµÄ´óС¶¼¿ÉÒÔÊDZäÁ¿——Õý·ûºÏÎÒÃǵÄÒªÇ󡣿´ÆðÀ´£¬ÊµÏÖÕâ¸ömulti_array²¢·ÇÄÑÊ£¬µ«ÊÂʵ×ÜÊdzöºõÒâÁÏ£¬ÏÂÃæ¾ÍÊǶÔboostÖÐÒÑÓеÄÒ»¸ömulti_arrayʵÏֵįÊÎö——Ä㼸ºõ¿Ï¶¨»á·¢ÏÖһЩ³öºõÒâÁϵģ¨ÉõÖÁÊÇÁîÈ˾ªÆæµÄ£©µØ·½¡£
BoostÖеĶàάÊý×éʵÏÖ——boost::multi_array
ÔÚBoost¿âÖоÍÓÐÒ»¸öÓÃÓÚÃèÊö¶àάÊý×éµÄ¹¦ÄÜÇ¿´óµÄMultiArray¿â¡£ËüʵÏÖÁËÒ»¸öͨÓá¢Óë±ê×¼¿âµÄÈÝÆ÷Ò»ÖµĽӿڣ¬²¢ÇÒ¾ßÓÐÓëC++ÖÐÄÚ½¨µÄ¶àάÊý×éÒ»ÑùµÄ½çÃæºÍÐÐΪ¡£ÕýÊÇ»ùÓÚÕâÖÖͨÓÃÐÔµÄÉè¼Æ£¬MultiArray¿âÓë±ê×¼¿â×é¼þÉõÖÁÓû§×Ô¶¨ÒåµÄ·ºÐÍ×é¼þÖ®¼ä¿ÉÒÔ¾ßÓкܺõļæÈÝÐÔ£¬²¢Äܹ»ºÜºÃµÄÐͬ¹¤×÷¡£
³ý´ËÖ®Í⣬MultiArray»¹ÌṩÁËÖîÈç¸Ä±ä´óС¡¢ÖØËÜ£¨reshaping£©ÒÔ¼°¶Ô¶àάÊý×éµÄÊÓͼ·ÃÎʵȼ«ÎªÓÐÓõÄÌØÐÔ£¬´Ó¶øÊ¹MultiArray±ÈÆäËüÃèÊö¶àάÊý×éµÄ·½Ê½£¨Æ©È磺std::vector< std::vector<...> > £©¸üΪ±ã½Ý¡¢¸ßЧ¡£
ÏÂÃæÎÒÃǾÍÖð²ãÉîÈ룬ȥ½Ò¿ªboost::multi_arrayµÄÉñÃØÃæÉ´——¶ÔʾÀý³ÌÐò½øÐе÷ÊÔ¡¢¸ú×ÙÊÇ·ÖÎö¿âÔ´´úÂë×îÓÐЧµÄÊÖ¶ÎÖ®Ò»¡£ÎÒÃǾʹÓMultiArrayÎĵµÖеÄʾÀý³ÌÐòÈëÊÖ£º
// ÂÔȥͷÎļþ°üº¬
int main () {
// ´´½¨Ò»¸ö³ß´çΪ3×4×2µÄÈýάÊý×é
#define DIMS 3 //Êý×éÊǼ¸Î¬µÄ
typedef boost::multi_array<double,DIMS> array_type; // (1-1)
array_type A(boost::extents[3][4][2]); // (1-2)
// ΪÊý×éÖÐÔªËØ¸³Öµ
A[1][2][0] = 120; // (1-3)
... ...
return 0;
}
ÔÚÉÏÊö´úÂëÖУ¬boost::multi_arrayµÄÁ½¸öÄ£°å²ÎÊý·Ö±ð´ú±íÊý×éÔªËØµÄÀàÐͺÍÊý×éµÄά¶È¡££¨1-2£©´¦ÊÇÈýάÊý×é¶ÔÏóµÄ¹¹ÔìÓï¾ä¡£boost::extents[3][4][2]ÔòÓÃÓÚÖ¸Ã÷¸ÃÊý×é¸÷άµÄ´óС£¬ÕâÀïµÄº¬ÒåÊÇ£º¶¨ÒåÒ»¸ö3*4*2µÄÈýάÊý×é¡£Äã¿Ï¶¨¶Ôboost::extentsÐÄ´æÒÉ»ó——Ϊʲô¶ÔËü¿ÉÒÔÁ¬ÓÓ[]”£¿Èç¹ûÓöàÁËÒ»¸ö»òÓÃÉÙÁËÒ»¸ö“[]”ÓÖ»áÈçºÎ£¿ÏÂÃæÎÒ¾ÍΪÄã²ã²ã°þ¿ªboost::extentsµÄËùÓаÂÃØ——
extents——ÓëÄÚ½¨Êý×éÒ»Öµķ½Ê½
boost::extentsÊÇÒ»¸öÈ«¾Ö¶ÔÏó£¬ÔÚbase.hppÖУº
typedef detail::multi_array::extent_gen<0> extent_gen;
... ...
multi_array_types::extent_gen extents; //×¢ÒâËüµÄÀàÐÍ£¡
¿É¼ûextentsµÄÀàÐÍΪextent_gen£¬ºóÕßλÓÚextent_gen.hppÖУº
// extent_gen.hpp
template <std::size_t NumRanges>
class extent_gen {
range_list ranges_; // £¨2-1£©
... ...
extent_gen(const extent_gen<NumRanges-1>& rhs, const range& a_range)
{ // £¨2-2£©
... //
}
extent_gen<NumRanges+1> operator[](index idx) //(2-3)
{ return extent_gen<NumRanges+1>(*this,range(0,idx)); }
//·µ»ØÒ»¸öextent_gen£¬²»¹ýµÚ¶þ¸öÄ£°å²ÎÊýÔö¼ÓÁË1
};
boost::extent_genÖØÔØÁËoperator[]²Ù×÷·û£¬µ«ÊÇ£¬¼ÈÈ»ÕâÀïÖ»ÓÐÒ»¸ö“[]”£¬ÎªÊ²Ã´ÎÒÃÇ¿ÉÒÔд“extents[n1][n2][n3][...]ÄØ£¿¼ÌÐø¿´——
Èç¹û°Ñboost::extents[n1][n2][n3]Õ¹¿ªÎª²Ù×÷·ûµ÷Óõķ½Ê½¾ÍÏ൱ÓÚ£º
boost::extents.operator[](n1).operator[](n2).operator[](n3);
boost::extents¶ÔÏóµÄÀàÐÍÊÇextent_gen<0> ——ÆäNumRangesÄ£°å²ÎÊýΪ0¡£extents.operator[](n1)µ÷Óã¨2-3£©£¬·µ»ØÒ»¸öextent_gen<NumRanges+1>£¬Ò²¾ÍÊÇextent_gen<1>£¬ÓÉÓÚÕâ¸öÀàÐÍÒ²ÊÇextent_gen£¬ËùÒÔÈÔÈ»¿ÉÒÔ¶ÔËüµ÷ÓÃoperator[](n2)£¬·µ»Øextent_gen<2>£¬È»ºóÔٶԸ÷µ»ØÖµµ÷ÓÃoperator[](n3)£¬×îÖÕ·µ»ØÒ»¸öextent_gen<3>ÀàÐ͵ĶÔÏó¡£
ÕâÀï£¬Ã¿Ò»ÖØoperator[]µ÷Óö¼×ªµ½£¨2-3£©£¬ÔÚÄÇÀォ²ÎÊýidxÒÔrange°ü×°Ò»ÏÂÔÙת·¢¸ø¹¹Ô캯Êý£¨2-2£©£¬×¢Òâ´Ëʱµ÷ÓõÄÊÇextent_gen<NumRange+1>ÀàÐ͵Ĺ¹Ô캯Êý¡£ÖÁÓÚrange(0,idx)Ôò±íʾһ¸ö[0,idx)µÄϱêÇø¼ä¡£
×ܽáÒ»ÏÂextentsµÄ»ù±¾¹¤×÷·½Ê½——ÿ¶ÔËüµ÷ÓÃÒ»´Îoperator[]£¬¶¼»á·µ»ØÒ»¸öextent_gen<NumRange+1>ÀàÐ͵ĶÔÏó£¬ËùÒÔ£¬¶ÔÓÚboost::extents[n1][n2][n3]£¬ÒÀ´Î·µ»ØµÄÀàÐÍÊÇ£º
extent_gen<1> => extent_gen<2> => extent_gen<3>
×îºóÒ»¸öÒ²ÊÇ×îÖյķµ»ØÀàÐÍ——extent_gen<3>¡£ÆäÄ£°å²ÎÊý3±íʾÕâÊÇÓÃÓÚÈýάÊý×éµÄϱêÖ¸¶¨¡£Æä³ÉÔ±ranges_ÖУ¬¹²ÓÐ[0£¬n1£©¡¢[0£¬n2£©¡¢[0£¬n3£©Èý×éÇø¼ä¡£ÕâÈý×éÇø¼äÖ¸¶¨ÁËÎÒÃǶ¨ÒåµÄmulti_array¶ÔÏóµÄÈý¸öά¶ÈµÄϱêÇø¼ä£¬ÖµµÃ×¢ÒâµÄÊÇÕâÐ©Çø¼ä¶¼ÊÇǰ±Õºó¿ªµÄ£¨ÕâºÍSTLµÄµü´úÆ÷±íʾµÄÇø¼äÒ»Ñù£©¡£µ±boost::extents×¼±¸Íê±Ïºó£¬¾Í±»´«Èëmulti_arrayµÄ¹¹Ô캯Êý£¬ÓÃÓÚÖ¸¶¨¸÷άµÄϱêÇø¼ä£º
// multi_array.hpp
explicit multi_array(const extent_gen<NumDims>& ranges):
super_type((T*)initial_base_,ranges){
allocate_space(); // £¨2-5£©
}
ÕâÀmulti_array½ÓÊÜÁËranges²ÎÊýÖеÄÐÅÏ¢£¬È¡³öÆäÖи÷άµÄϱêÇø¼ä£¬È»ºó±£´æ£¬×îºóµ÷ÓÃallocate_space()À´·ÖÅäµ×²ãÄÚ´æ¡£
ʹÓÃextent_genµÄºÃ´¦——do things right!
ʹÓÃboost::extents×÷²ÎÊýµÄ¹¹Ôì¹ý³ÌºÍÄÚ½¨¶àάÊý×éµÄ·½Ê½Ò»Ö£¬¼òÁ·Ö±¹Û£¬ÓïÒåÇåÎú¡£Ê×ÏÈ£¬boost::extentsʹÓÓ[]”£¬ÄÜÈÃÈ˺ÜÈÝÒ×Ïëµ½ÄÚ½¨¶àάÊý×éµÄÉùÃ÷£¬Ò²ºÜÇåÎúµØ±í´ïÁËÿ¸ö·½À¨ºÅÖÐÊýÖµµÄº¬Òå——±íÃ÷¸÷ά¶ÈµÄϱêÇø¼ä£»×î¹Ø¼üµÄ»¹ÊÇ£¬Ê¹ÓÃboost::extents£¬¿ÉÒÔ·ÀÖ¹Óû§Ò»²»Ð¡ÐÄд³ö´íÎóµÄ´úÂ룬ÀýÈ磺
multi_array<int,3> A(boost::extents[3][4][2][5]);
//´í£¡²»ÄÜÓÃËÄάµÄϱêÖ¸¶¨À´´´½¨Ò»¸öÈýάÊý×é!
ÉÏÃæµÄÓï¾äÊÇÍêÈ«´íÎóµÄ£¬ÒòΪmult_arrayÊǸöÈýάÊý×飬¶øboost::extentsºóÃæÈ´¸úÁËËĸö“[]”£¬ÕâÏÔÈ»ÊǸö´íÎó¡£Õâ¸ö´íÎó±»½ûÖ¹ÔÚ±àÒëÆÚ£¬ÕâÊÇÓÉÓÚÔÚÓï·¨²ãÃæ£¬multi_array<int,3>µÄ¹¹Ô캯ÊýÖ»ÄܽÓÊÜextent_gen<3>ÀàÐ͵IJÎÊý£¬¶ø¸ù¾ÝÎÒÃÇÇ°Ãæ¶ÔextentsµÄ·ÖÎö£¬boost::extents[3][4][2][5]·µ»ØµÄÈ´ÊÇextent_gen<4>ÀàÐ͵ĶÔÏó£¬ÓÚÊǾͻá²úÉú±àÒë´íÎó¡£ÕâÖÖ±àÒëÆÚµÄÇ¿ÖÆ´ëÊ©×èÖ¹ÁËÓû§Ò»²»Ð¡ÐÄ·¸ÏµĴíÎó£¨Èç¹ûÄãÕýÔÚ´òî§Ë¯ÄØ£¿£©£¬Ò²ºÜÇåÎúÃ÷Á˵رí´ï£¨Ç¿ÖÆ£©ÁËÓïÒåµÄÐèÇó¡£
ÁíÒ»ÖÖÌæ´ú·½°¸¼°Æäȱµã
ÁíÍ⣬»¹ÓÐÒ»ÖÖÉùÃ÷¸÷ά´óСµÄÌæ´ú·½Ê½£¬¾ÍÊÇʹÓÃËùνµÄCollection Concept£¬ÀýÈ磺
// ÉùÃ÷Ò»¸öshape£¨“ÐÎ×´”£©£¬¼´¸÷¸öά¶ÈµÄsize
boost::array<int,3> shape = {{ 3, 4, 2 }};
array_type B(shape); //3*4*2µÄÈýάÊý×é
ÕâÖÖ¹¹Ô췽ʽ½«µ÷ÓÃmulti_arrayµÄµÚ¶þ¸ö¹¹Ô캯Êý£º
// multi_array.hpp
template <class ExtentList>
explicit multi_array( ExtentList const& extents ) :
super_type((T*)initial_base_,extents) {
boost::function_requires< // £¨2-4£©
detail::multi_array::CollectionConcept<ExtentList> >();
allocate_space(); // £¨2-6£©
}
Õâ¸ö¹¹Ô캯ÊýµÄÐβÎextentsÖ»ÒªÊÇ·ûºÏcollection concept¾Í¿ÉÒÔÁË——shapeµÄÀàÐÍΪboost::array£¬µ±È»·ûºÏÕâ¸öconcept¡£Õâ¸ö¹¹Ô캯ÊýµÄÐÐΪÓë½ÓÊÜextents_genµÄ¹¹Ô캯ÊýÊÇÒ»ÑùµÄ——ÈÔÈ»ÊÇÏÈÈ¡³ö¸÷άµÄrange±£´æÏÂÀ´£¬È»ºó·ÖÅäµ×²ãÄÚ´æ¡£ÖÁÓÚ£¨2-4£©´¦µÄ´úÂ룬ÔòÊÇΪÁËÔÚ±àÒëÆÚ¾²Ì¬¼ì²éÄ£°å²ÎÊýExtentListÊÇ·ñ·ûºÏCollection concept£¬ÊµÏÖϸ½ÚÔڴ˲»ÔÙ׸Êö¡£
°ÑÕâÖÖ·½Ê½ÓëʹÓÃextent_genµÄ·½Ê½×÷Ò»¸ö¼òµ¥µÄ±È½Ï£¬ºÜÈÝÒ׾Ϳ´³öÓÅÁÓ£º²ÉÓÃÕâÖÖ·½Ê½£¬¾Í²»Äܱ£Ö¤±àÒëÆÚÄܹ»½øÐÐÕýÈ·ÐԵļì²éÁË£¬ÀýÈ磺
boost::array<int,4> shape = {{3,4,2,5}}; //Ò»¸öËÄάÊý×éµÄshape
multi_array<int,3> A(shape); // ¾¹È»¿ÉÒÔͨ¹ý±àÒ룡£¡
ÕâÀÓÃÒ»¸öËÄάµÄshapeÀ´Ö¸¶¨Ò»¸öÈýάmulti_arrayÊDz»Ç¡µ±µÄ£¬µ«ÊÇȴͨ¹ýÁ˱àÒ룬ÕâÊÇÓÉÓڸù¹Ô캯Êý¶ÔËüµÄ²ÎÊýextentsÃ»Ê²Ã´ÌØÊâÒªÇó£¬Ö»ÊǰÑËü×÷Ϊһ¸öÆÕͨµÄcollectionÀ´¶Ô´ý£¬¹¹Ô캯Êý»á¸ù¾Ý×Ô¼ºµÄÐèÒª´ÓextentsÖÐÈ¡³öËüËùÐèÒªµÄ¸÷άϱêÇø¼ä——AÊÇÈýάÊý×飬ÓÚÊǹ¹Ô캯Êý´ÓshapeÖÐÈ¡³öǰÈý¸öÊýÖµ×÷ΪAÈý¸öά¶ÈµÄϱêÇø¼ä£¬¶ø²»¹Üshape¾¿¾¹°üº¬Á˼¸¸öÊýÖµ¡£ÕâÑùµÄÓï¾äÔÚÓïÒåÉÏÊDz»ÇåÎúÉõÖÁ´íÎóµÄ¡£µ«ÊǼÈÈ»ÕâÑùµÄ¹¹Ô캯Êý´æÔÚ£¬Éè¼ÆÕß×ÔÈ»ÓÐËûµÄµÀÀí£¬ÎĵµÖоÍÃ÷È·µÄ±íÃ÷£¬Õâ¸ö¹¹Ô캯Êý×î´óµÄÓô¦¾ÍÊDZàдά¶ÈÎ޹أ¨dimension-independent£©µÄ´úÂ룬³ý´ËÖ®Íâmulti_array¿âĬÈÏΪǰһÖÖ¹¹Ô캯Êý¡£
multi_arrayµÄ¼Ü¹¹
ÎÞÂÛ²ÉÓÃÄÄÒ»ÖÖ¹¹Ô캯Êý£¬¹¹ÔìµÄÁ÷³Ì¶¼ÊÇÏàËÆµÄ——½«Ò»ÏµÁÐϱêÇø¼ä´«Èë»ùÀàµÄ¹¹Ô캯ÊýÖÐÈ¥£¬»ùÀ๹ÔìÍê³ÉÖ®ºó¾Íµ÷ÓÃÏàͬµÄallocate_space()º¯Êý£¨¼û£¨2-5£©ºÍ£¨2-6£©´¦£©£¬allocate_space£¬¹ËÃû˼Ò壬ÓÃÓÚΪ¶àάÊý×éµÄÔªËØ·ÖÅä¿Õ¼ä¡£
È»¶ø£¬ÔÚÕâ¸ö¿´ËƼòµ¥µÄ¹¹Ôì¹ý³Ì±³ºó£¬È´Òþ²ØÁËÁ½Èý²ã²ã´Î½á¹¹£¬Ã¿²ãµÄ½á¹¹ºÍ¹¦Äܶ¼ÓÐËù²»Í¬£¬µ£ÈÎÁ˲»Í¬µÄ½ÇÉ«£¬ÓÐЩ²ã´ÎÔòÄܹ»µ¥¶ÀÀ³öÀ´¸´ÓÃÓÚÆäËûµØ·½¡£
ÏÂÃæÎÒÃǾÍÀ´¿´¿´multi_arrayµÄ¼Ü¹¹µ½µ×³¤Ê²Ã´ÑùJÊ×ÏÈ£¬multi_array¼Ì³Ð×Ômulti_array_ref£º
// multi_array_ref.hpp
template <typename T, std::size_t NumDims>
class multi_array_ref : //multi_arrayµÄ»ùÀ࣡£¡
public const_multi_array_ref<T,NumDims,T*>
{
typedef const_multi_array_ref<T,NumDims,T*> super_type;
... ...
explicit multi_array_ref(T* base, //Ö¸ÏòÊý×é´æ´¢¿Õ¼äµÄÖ¸Õë
const extent_gen<NumDims>& ranges): //ϱêÇø¼ä
super_type(base,ranges) //°Ñ³õʼ»¯µÄÈÎÎñת·¢¸ø»ùÀࣨ3-1£©
{ }
... ...
};
¶ømulti_array_refÓÖÒÔconst_multi_array_refΪ»ùÀࣺ
// multi_array_ref.hpp
class const_multi_array_ref : //multi_array_refµÄ»ùÀà!¹ÜÀíµ×²ã´æ´¢£¡
public multi_array_impl_base<T,NumDims>
{
... ...
explicit const_multi_array_ref(TPtr base,
const extent_gen<NumDims>& ranges) :
base_(base), storage_(c_storage_order()) // £¨3-2£©
{ init_from_extent_gen(ranges); }
... ...
storage_order_type storage_;//Ö§³Ö¶àÖÖ´æ´¢²ßÂÔ£¡£¨3-3£©
};
multi_arrayµÄ¹¹Ôì֮·;¾£¨3-1£©´¦£¨multi_array_refµÄ¹¹Ô캯Êý£©£¬ÑÓÉìÖÁ£¨3-2£©´¦£¨const_multi_array_refµÄ¹¹Ô캯Êý£©——ÕâÀï¿´ËÆÒ»¸öÖսᣬÒòΪÔÙûÓвÎÊý´«µÝ¸ø const_multi_array_refµÄ»ùÀàmulti_array_impl_baseÁË¡£µ«ÊÇÐÄÖл¹ÊÇÒÉ»ó£ºÎªÊ²Ã´»áÓÐÈç´Ë¶à²ãµÄ¼Ì³Ð½á¹¹£¿ÕâÑùµÄÀà²ã´Î½á¹¹Éè¼Æ¾¿¾¹ÓÐʲôÐþ»úÄØ£¿
¶à²ã¼Ì³ÐµÄ°ÂÃØ——·ÃÎʽçÃæ&&¸´ÓÃÐÔ
תµ½»ùÀàconst_multi_array_refµÄÉùÃ÷£¬Ëƺõ¿ÉÒÔ¿´³öһЩ¶ËÄߣº
template< ... >
class const_multi_array_ref {
... ...
//ºÍËùÓеÄSTLÈÝÆ÷Ò»Öµĵü´úÆ÷½çÃæ£¡£¡
const_iterator begin() const;
const_iterator end() const;
... ...
//ºÍstd::vectorÒ»ÖµÄÔªËØ·ÃÎʽçÃæ£¡£¡
const_reference operator[](index i) const;
... ...
};
¿´µ½ÉÏÃæÕâЩÉùÃ÷£¬ÊDz»ÊÇÓÐÐ©ÃæÊ죿STL£¡¶Ô£¬ÕâЩ³ÉÔ±º¯ÊýµÄÉùÃ÷ÊÇÓëSTLÖÐcontainer conceptÍêȫһÖµġ£Ò²¾ÍÊÇ˵£¬ÕâÀïÌṩÁËÓëSTLÈÝÆ÷Ò»ÖµķÃÎʽçÃæ£¬ËùνÓëSTLµÄ¼æÈÝÐÔÕýÊÇÔÚÕâÀïÌåÏÖ³öÀ´ÁË¡£¶øconst_multi_array_ref¸üÊÇ“ÀàÈçÆäÃû”£¬const_multi_array_refÖÐËùÓзÃÎÊÔªËØ¡¢²éѯÊý×éÐÅÏ¢µÈ³ÉÔ±º¯Êý¶¼·µ»ØconstµÄreference»òiterator¡£¶ø·´¹Ûmulti_array_refµÄÉùÃ÷£¬ÆäÖÐÖ»±Èconst_multi_array_ref¶àÁË·ÃÎÊÔªËØ¡¢²éѯÊý×éÐÅÏ¢µÄ¶ÔÓ¦µÄnon-const°æ±¾³ÉÔ±º¯Êý¡£
ÄÇôconst_multi_array_refµÄ»ùÀàmulti_array_impl_baseµÄÖ°ÔðÓÖÊÇÊ²Ã´ÄØ?multi_array_impl_baseÊÇÊôÓÚʵÏÖϸ½ÚµÄ£¬ËüµÄ×÷ÓÃÖ»ÊǸù¾ÝÊý×éÐÅÏ¢£¨const_multi_array_refÖеijÉÔ±±äÁ¿£©¼ÆËãÆ«ÒÆÁ¿¡¢²½³¤µÈ£¬Ò²¾ÍÊǰѶàάµÄϱê×îÖÕת»¯ÎªÒ»Î¬Æ«ÒÆÁ¿¡£¶ømulti_array_impl_baseµÄ»ùÀà——value_accessor_n»òÕßvalue_accessor_one——µÄ¹¦ÄÜÔòÊÇÌṩһ¸ö¶ÔÔʼÊý¾ÝµÄ·ÃÎÊ¡£ÕâÖÖ·ÃÎÊ·½Ê½ÊÇ´ó¼ÒËùÊìϤµÄ°Ñ¶àάË÷Òýת»¯ÎªÒ»Î¬Æ«ÒÆÁ¿µÄ·½Ê½——·²ÊÇд¹ýÓÃһάÊý×éÄ£Äâ¶àάÊý×éµÄÈ˶¼Ó¦¸ÃÇå³þ¡£ÖÁÓÚΪʲôҪÓÐvalue_accessor_nºÍvalue_accessor_oneÁ½¸ö°æ±¾£¬ºóÎÄ»áÏêϸ²ûÊÍ¡£
ÖÁ´Ë£¬multi_arrayµÄ´óÖ¼ܹ¹¾ÍÒѾ¸¡ÏÖ³öÀ´ÁË£º
multi_array -> multi_array_ref -> const_multi_array_ref -> multi_array_impl_base -> value_accessor_n/value_accessor_one
ÆäÖÐÿһ²ã¶¼µ£Èθ÷×ԵĽÇÉ«£º
¨ multi_array : ΪÊý×éÔªËØ·ÖÅä¿Õ¼ä£¬½«¸÷ÖÖ²Ù×÷ת·¢ÖÁ»ùÀà¡£
¨ multi_array_ref : ÌṩÓëSTLÈÝÆ÷Ò»ÖµÄÊý¾Ý·ÃÎʽçÃæ¡£Ò²¿ÉÒÔ¶ÀÁ¢³öÀ´×÷Ϊһ¸öadapterʹÓá£
¨ const_multi_array_ref : ÌṩconstµÄSTLÊý¾Ý·ÃÎʽçÃæ¡£Ò²¿ÉÒÔ×÷Ϊһ¸öconst adapterʹÓá£
¨ multi_array_impl_base¼°Æä»ùÀà :×îµ×²ãʵÏÖ£¬Ìṩһ×é¶ÔÔʼÊý¾ÝµÄ»ù±¾²Ù×÷¡£
ÕâÖּܹ¹¿´ËƸ´ÔÓ£¬È´ÌṩÁ˺ܸߵĸ´ÓÃÐÔ£¬ÆäÖеÄ(const_)multi_array_refÀà¶¼¿ÉÒÔ¶ÀÁ¢³öÀ´×÷Ϊһ¸öadapterʹÓ×—ÀýÈ磺
int a[24]; //һάµÄ10¸öÔªËØÊý×飬λÓÚÕ»ÉÏ£¡
//°ÑһάÊý×éa“¿´³É”Ò»¸ö3*4*2µÄÈýάÊý×飺
multi_array_ref<int,3> arr_ref(a,boost::extents[3][4][2]);
arr_ref[i][j][k] = value; //ºÍmulti_arrayÒ»ÑùµÄʹÓýçÃæ
ºÜ¼òµ¥°É£¡´Ó´ËÄã¾Í²»ÓÃÐÁÐÁ¿à¿àµÄȥģÄâ¶àάÊý×éÁË¡£¼´Ê¹ÊÇλÓÚÕ»ÉϵÄһάÊý×飬Ҳ¿ÉÒÔ°ÑËü“¿´³É”ÊÇÒ»¸ö¶àάÊý×é¡£ÌÈÈôÄã²»ÏëÈÃmulti_arrayÀ´×Ô¶¯·ÖÅäÄÚ´æµÄ»°£¬Äã¿ÉÒÔ×ÔÐзÖÅäÊý×飨¿ÉÒÔλÓÚÕ»ÉÏ»ò¶ÑÉÏ£©È»ºóÓÃmulti_array_ref°ÑËü°ü×°³ÉÒ»¸ö¶àάµÄÊý×é¡£
multi_arrayµÄ´æ´¢²ßÂÔ
½ÓÏÂÀ´£¬¾ÍÀ´¿´¿´multi_arrayµÄ´æ´¢²ßÂÔ£¬ÀýÈ磺C·ç¸ñµÄ¶àάÊý×é´æ´¢·½Ê½Êǰ´Ðд洢£¬¶øfortranǡǡÏà·´£¬Êǰ´Áд洢£¬ÉõÖÁ£¬Óû§¿ÉÄÜÓÐ×Ô¼ºµÄ´æ´¢²ßÂÔÒªÇó¡£ÄÇô£¬ÈçºÎÖ§³Ö¶àÖÖ·ç¸ñµÄ´æ´¢²ßÂÔÄØ£¿ÃØÃܾÍÔÚÓÚ´úÂ루3-3£©´¦£¬const_multi_array_refµÄ³ÉÔ±storage_——ÆäÀàÐÍΪstorage_order_type£¬ÏÂÃæµÄÉùÃ÷Ö¸³öÁËstorage_order_typeµÄ“±¾À´ÃæÄ¿”——general_storage_order<NumDims>£º
// multi_array_ref.hpp
... ...
typedef general_storage_order<NumDims> storage_order_type;
... ...
// storage_order.hpp
template <std::size_t NumDims>
class general_storage_order {
general_storage_order(const c_storage_order&){ //£¨4-1£©
for (size_type i=0; i != NumDims; ++i)
{ ordering_[i] = NumDims - 1 - i; }
ascending_.assign(true); //ȱʡΪÉýÐòÅÅÁÐ
}
... ...
boost::array<size_type,NumDims> ordering_; //¸÷άµÄÓÅÏÈ˳Ðò
boost::array<bool,NumDims> ascending_;//ÉýÐòÅÅÁл¹ÊǽµÐòÅÅÁÐ
};
ÔÚ£¨4-1£©´¦µÄ¹¹Ô캯ÊýÖУ¬ordering_ºÍascending_ÊÇÁ½¸öÊý×飬ȱʡÇé¿öÏ£¬µ±º¯Êý£¨4-1£©Ö´ÐÐÍê±Ïºó£¬ordering_ÖеÄÔªËØÓ¦µ±ÊÇ{NumDims-1, NumDims-2,...1,0}£¬Ò²¾ÍÊÇ˵£¬NumDims-1άÔÚÏÈ£¬È»ºóÊÇNumDims-2ά£¬...£¬Èç¹û½«ÕâÐ©ÔªËØ×÷Ϊ¸÷ά¶È´æ´¢Ë³ÐòµÄ±êʶ——¾ßÓнÏСordering_ÖµµÄά¶ÈÓÅÏÈ——ÄÇô¾ÍÕâºÍCÓïÑÔÖеĴ洢·½Ê½¾ÍÍêȫһÖÂÁË£¬¶øascending_ÎðÓ¹ÖÃÒɾÍÊÇÓÃÀ´±íÃ÷¸÷ά¶ÈÊÇ·ñÉýÐò´æ´¢¡£Æäʵgeneral_storage_order»¹ÓÐÒ»¸öÄ£°å¹¹Ô캯Êý£¬ËüÊÇΪÁËÖ§³Ö¸üΪһ°ã»¯µÄ´æ´¢²ßÂÔ£¨ÀýÈçfortranµÄ°´Áд洢»òÓû§×Ô¶¨ÒåµÄ´æ´¢²ßÂÔ£©¡£ÕâÀï²»×÷ÏêÊö¡£
³ýÁË´æ´¢²ßÂÔ£¬const_multi_array_refµÄ¹¹Ô컹ͨ¹ýµ÷ÓÃinit_from_extent_genº¯Êý£¬½«extentsÖеÄÄÚÈÝÈ¡³öÀ´½øÐд¦Àí£¬²¢ÒÔ´ËÉ趨ÆäËüÈô¸É±íÊö¶àάÊý×éµÄ±äÁ¿£¨£¨3-3£©´¦ÆäËüһЩ±äÁ¿£©£¬¾ßÌåϸ½Ú²»ÔÙ׸Êö¡£
ÏÖÔÚ¹ØÓÚÒ»¸ö¶àάÊý×éµÄËùÓÐÐÅÏ¢¶¼ÒѾ׼±¸Æë±¸£¬¿Éν“Íòʾ߱¸£¬Ö»Ç·‘¿Õ¼ä’”¡£multi_arrayÏÂÃæÒª×öµÄ¾ÍÊǵ÷ÓÃÇ°ÃæÌáµ½µÄallocate_spaceÀ´ÎªÊý×éÖеÄÔªËØ·ÖÅä¿Õ¼äÁË¡£
// multi_array.hpp
void allocate_space() {
... ...
base_ = allocator_.allocate(this->num_elements(),no_hint);
... ... std::uninitialized_fill_n(base_,allocated_elements_,T());
}
ÔÀ´£¬Ôڵײ㣬´æ´¢ÈÔÈ»ÊÇÍË»¯ÎªÒ»Î¬Êý×éµÄ´æ´¢£º allocate_spaceʹÓÃallocator_·ÖÅäÒ»¿éÁ¬ÐøµÄ¿Õ¼äÓÃÒÔ´æ´¢ÔªËØ£¬ÆäÖÐnum_elements()·µ»ØµÄ¾ÍÊÇÊý×é¸÷ά¶ÈµÄ´óСµÄ³Ë»ý£¬¼´Êý×éµÄ×ÜÔªËØ¸öÊý¡£·ÖÅäÍêÖ®ºó£¬¾Í½«Ê×Ö¸Õ븳¸ø±íÊöÊý×é»ùµØÖ·µÄ³ÉÔ±base_£¬È»ºóstd::uninitialized_fill_n¸ºÔð°Ñ¸ÃÊý×é½øÐÐȱʡ³õʼ»¯¡£ÖÁ´Ëmulti_arrayµÄ¹¹Ô칤×÷ÖÕÓڴ󹦸æ³ÉÁË¡£
Ò»ÖÂÐÔ½çÃæ——GPµÄÁé»ê
multi_arrayµÄÁíÒ»ÖØÒªÌØÐÔ¾ÍÊÇÖ§³ÖÓëÄÚ½¨¶àάÊý×éÏàͬµÄ·ÃÎÊ·½Ê½£¬Ò²¾ÍÊÇ˵£¬multi_arrayÖ§³ÖÒÔÁ¬ÐøµÄ“[]”À´·ÃÎÊÊý×éÔªËØ¡£¾ÍÒÔÎÄÕ¿ªÍ·¸ø³öµÄʾÀý´úÂ루1-3£©´¦µÄ¸³ÖµÓï¾äΪÀý£¬ÈÃÎÒÃÇ¿´¿´multi_arrayÊÇÈçºÎÖ§³ÖÕâÖÖÓëÄÚ½¨Êý×鼿ÈݵķÃÎÊ·½Ê½µÄ¡£
// multi_array_ref.hpp
// ʹÓÃoperator[]À´·ÃÎÊÔªËØ,·µ»ØÀàÐÍreferenceÊÇÊ²Ã´ÄØ£¿²»ÊÇT&!
reference operator[](index idx) {
return super_type::access(boost::type<reference>(),
idx,origin(),this->shape(),this->strides(),
this->index_bases());
}
Õâ¸öµ÷ÓÃתÈëÁËvalue_accessor_n::access(...)Ö®ÖУº
// base.hpp
// in class value_accessor_n
template <typename Reference, typename TPtr>
Reference access(boost::type<Reference>,
index idx,TPtr base,const size_type* extents,
const index* strides,const index* index_base)
{
TPtr newbase = base + idx * strides[0];
return Reference(newbase,extents+1,
strides+1,index_base+1);
}
Õâ¸öÁ¬Ðøµ÷ÓÃoperator[]µÄ¹ý³ÌºÍextend_genÊǺÜÀàËÆµÄ——ÿµ÷ÓÃÒ»²ã¾Í·µ»ØÒ»¸ö“proxy(ÌæÉí)”£¬Õâ¸öÌæÉí²¢·Çʵ¼ÊÔªËØ£¬ÒòΪÕâʱºòºóÃæ»¹¸úÓГ[]”£¬ËùÒÔ¶ÔÕâ¸öÌæÉíÒ²Ó¦¸ÃÄܵ÷ÓÃoperator[]£¬´Ó¶øÊ¹Õâ¸ö¹ý³ÌÄܹ»Á¬ÐøÏÂÈ¥Ö±µ½ºóÃæÃ»ÓГ[]”Ϊֹ”¡£
¾Ù¸öÀý×Ó£¬Èç¹ûÒÔA[x1][x2][x3]·½Ê½·ÃÎÊAÖеÄÔªËØ£¬¾ÍÏ൱ÓÚ
A.operator[x1].operator[x2].operator[x3] //Á¬Ðøµ÷ÓÓ[]”
ÕâÈý´Îoperator[]µ÷Ó÷µ»ØµÄÀàÐÍÒÀ´ÎΪ£º
sub_array<T,2> -> sub_array<T,1> -> T&
×¢Òâsub_arrayµÄµÚ¶þ¸öÄ£°å²ÎÊý£¨Î¬¶È£©µÝ¼õµÄ¹ý³Ì£¬µ±µÝ¼õµ½0ʱ£¬±íÃ÷ÒѾµÝ¹éµ½ÁË×îºóÒ»¸öά¶È£¬ÕæÕýµÄ·ÃÎÊ¿ªÊ¼ÁË£¬ËùÒÔ×îºóÒ»´Îµ÷ÓÓ[]”·µ»ØµÄÇ¡ºÃÊǶÔÔªËØµÄÒýÓã¨Õâ¾Í¸ÕºÃÓ¡Ö¤ÁËÇ°ÃæËù˵µÄ——µ±ÇÒ½öµ±“[]”µÄ¸öÊýºÍÊý×éµÄάÊýÏàͬµÄʱºò£¬²ÅÄܹ»È¡³öÔªËØ£¬·ñÔòÄãµÃµ½µÄ·µ»ØÖµÒªÃ´»¹ÊÇsub_array<...>£¨¶ø²»ÊÇÔªËØ£©£¬ÒªÃ´»áÓÉÓÚÊÔͼÔÚT&ÉϼÌÐøµ÷ÓÓ[]”¶ø±àÒëʧ°Ü£©ÄÇô£¬ÕâÒ»Çо¿¾¹ÊÇÈçºÎ×öµ½µÄÄØ£¿
´ÓÉÏÃæµÄµÝ¹é¹ý³Ì£¬ÎÒÃÇ¿ÉÒÔÇáÒ׿´³ö£ºÕæÕý¶ÔÔªËØ½øÐзÃÎʲ¢·µ»ØT&µÄÈÎÎñ½»¸øÁËsub_array<T,1>¡£ÄÇôÕâ¸ösub_arrayµ½µ×ÊǸöʲô¶«¶«£¿
sub_arrayµÄÃØÃÜ
sub_arrayµÄ¶¨ÒåÔÚsub_array.hppÖУº
// sub_array.hpp
template <typename T, std::size_t NumDims>
class sub_array : public const_sub_array<T,NumDims,T*>;
template <typename T, std::size_t NumDims, typename TPtr>
class const_sub_array :
public multi_array_impl_base<T,NumDims>;
//base.hpp
template <typename T, std::size_t NumDims>
class multi_array_impl_base:public
value_accessor_generator<T,mpl::size_t<NumDims> >::type ;
ßí£¬ÔÀ´sub_array×îÖռ̳Ð×Ômulti_array_impl_base£¬ºóÕߵĻùÀàÐÍÓÉvalue_accessor_generatorÀ´Éú³É——Ëü»á¸ù¾ÝNumDimsµÄ²»Í¬¶øÉú³É²»Í¬µÄ»ùÀàÐÍ£º
// base.hpp
template <typename T, typename NumDims>
struct value_accessor_generator {
... ...
typedef typename //Èç¹ûNumDimsΪ1£¬ÔòÀàÐÍΪvalue_accessor_one
mpl::apply_if_c<(dimensionality == 1),
choose_value_accessor_one<T>,
choose_value_accessor_n<T,dimensionality>
>::type type; //°ÑÕâ¸öÀàÐÍ×÷Ϊmulti_array_impl_baseµÄ»ùÀ࣡
};
ºÜÏÔÈ»£¬Èç¹ûdimensionality == 1£¬ÄÇô“::type”¾ÍÊÇvalue_accessor_one<T>£¬¶øÖ»ÓжÔvalue_accessor_oneʹÓÓ[]”²ÅÄÜ·µ»ØT&£¬·ñÔò£¬“::type”±»ÍƵ¼Îªvalue_accessor_n£¬ÕâÖ»ÊǸö“proxy”¶øÒÑ£¬¶ÔËüÔËÓÓ[]”Ö»»á·µ»Øsub_array<T,NumDims-1>£¬´Ó¶ø¿ÉÒÔ¶ÔËü¼ÌÐøÕâ¸öÁ¬Ðøµ÷ÓÓ[]”µÄ¹ý³Ì£¬Ö±µ½dimensionality ½µÎª1£¬sub_arrayµÄ»ùÀà²Å±ä³ÉÁËvalue_accessor_one£¬ÕâʱºòÔÙʹÓÓ[]”¾Í»á·µ»ØT&£¡
È¡³öÔªËØ
¸ù¾ÝÉÏÃæµÄ·ÖÎö£¬È¡ÔªËصÄÈÎÎñ×îÖÕ½»¸øvalue_accessor_one£¬Æä³ÉÔ±º¯ÊýaccessÈçÏ£º
template <typename Reference, typename TPtr>
Reference access(boost::type<Reference>,index idx,TPtr base,
const size_type*,const index* strides,
const index*) const {
return *(base + idx * strides[0]); //ÖÕÓÚÈ¡³öÁËÊý¾Ý£¡
}
ÕâÀaccessµÄ·µ»ØÀàÐÍReference¾ÍÊÇT&£¬¼´Êý×éÖÐÔªËØÀàÐ͵ÄÒýÓ㬴Ӷø¿ÉÒÔ½«Ö¸¶¨ÔªËصÄÒýÓ÷µ»Ø£¬´ïµ½·ÃÎÊÊý×éÔªËØµÄÄ¿µÄ¡£¿´µ½ÕâÀmulti_arrayÒÔÄÚ½¨Êý×é·ÃÎÊ·½Ê½·ÃÎÊÊý×éÔªËØµÄ¹ý³Ì»ù±¾ÒѾŪÇå³þÁË£¬ÖÁÓÚÆäÖÐһЩϸ½Ú£¬ÓÈÆäÊǼÆËãµØÖ·µÄϸ½Ú£¬Æ©Èç£ºÆ«ÒÆÁ¿µÄ¼ÆËã¡¢²½³¤µÄʹÓ