C ++:数组的构造函数/初始化程序?

Posted

技术标签:

【中文标题】C ++:数组的构造函数/初始化程序?【英文标题】:C++: constructor / initializer for array? 【发布时间】:2011-03-07 16:11:31 【问题描述】:

我熟悉 C++ 构造函数和初始化器:

class Foo 
   int x;
public:
   Foo(int _x) : x(_x) 
;

Foo foo1(37);
Foo foo2(104);

我的问题是我必须实现一个具有 3x6 数组成员的类。我将如何做与上述类似的事情?

class Bar 
   int coeff[3][6];
public:
   // what do I do for a constructor????
;

编辑:对于一个普通的数组,我会做以下,我只是不知道如何为一个类做:

 static int myCoeffs[3][6] = 
   1,  2,  3,  4,  5,  6, 
    7,  8,  9, 10, 11, 12,
   13, 14, 15, 16, 17, 18;

编辑 2:由于各种原因(例如,这是一个有限制的嵌入式系统),我不需要使用 Boost,所以如果它提供了解决方案,我就不能使用它。


更新:我没有绑定到初始化程序。可以在构造函数体中做,也不必内联。我只是在寻找一种正确的方法来构造一个需要一个系数数组的类的实例,而不会弄乱指针分配之类的东西。

【问题讨论】:

哪个版本的 C++?如果您使用的是标准的当前 (C++03) 版本,则无法模仿初始化程序。 "old-school" C++ -- 这是针对嵌入式系统的,我不知道哪个版本的标准,甚至 2003 年可能太新了。 2003 是第一个标准化版本。 【参考方案1】:

你不能。在 C++03 中,您不能在 ctor-initialization 列表中初始化数组。但是,您可以在构造函数主体中执行此操作(从技术上讲,它不再是初始化)。

那是

struct x

    int a[4];
    x():a(1,2,3,4) //illegal
    
        a[0] = 1;
        etc. 
    
;

Edit: 问题编辑后这是一种方法

#include <algorithm>
struct x

   int arr[3][4];
   x(int (&arg)[3][4])
   
      std::copy(&arg[0][0], &arg[0][0]+3*4, &arr[0][0]);
   

;

【讨论】:

嗯,没关系,我只需要一些“好”的方法来做。 @Jason:我能想到的唯一“好”方法是在 ctor 中按成员初始化它们,例如 a[0] = 1; a[1] = 23; 等。 糟糕。啊,我想我只是传入一个数组,然后使用一对 for 循环来复制元素。 @Billy:不在 C++03 中。不确定 C++0x @Armen 代码中有一些问题:temp 应该是 staticconststd::copy 的参数应该是指向 int 的指针,例如&amp;temp[0][0], &amp;temp[0][0] + 3 * 4 - 所以还没有 +1【参考方案2】:

我不知道这听起来是不是太明显了,但是为什么不直接复制这些值呢?

class Foo 
    static const int X = 3;
    static const int Y = 6;

    int mCoeff[X][Y];

    void setCoeff(int coeff[X][Y]) 
        for (int i = 0; i < X; i++) 
            for (int j = 0; j < Y; j++) 
                mCoeff[i][j] = coeff[i][j];
            
        
    
public:
    Foo(int coeff[X][Y]) 
        setCoeff(coeff);
    

;

希望对您有所帮助。问候。

【讨论】:

这是错误的,原因与我最初的回答错误的原因相同。 这可能不是聪明或最有效的方法,但它适用于我的编译器。 好的,所以我不得不将int coeff[X][Y] 更改为int **pcoeff @Jason:那是完全错误的。 @redent84 的代码有效,但我似乎无法弄清楚为什么(因为它似乎与我在下面发布的完全相同,但我的没有编译..)。 int [x][y] 不是指向数组的指针数组。它是一个单个内存块int ** 是完全不同的类型。 按照 Jason 的建议,我更改了方法签名,以便它可以采用动态分配的整数数组。这种方式不检查数组边界,您可能会遇到分段违规错误。【参考方案3】:

在 C++03 中,由于无法在初始化列表中初始化数组,因此可以编写一个泛型函数模板来用给定数组填充数组,如下例所示,

template<typename T, size_t N>
void array_fill(T (&dest)[N], T (&src)[N])

   for ( size_t i = 0 ; i < N ; i++ )
       dest[i] = src[i];

struct A

   int a[5];
   A(int (&i)[5])  array_fill(a, i); 
   void print() 
   
      for ( int i = 0 ; i < 5 ; i++ ) cout << a[i] << " ";
   
;
int main() 
        int a[5] = 1,2,3,4,5;
        A obj(a);
        obj.print();
        return 0;

输出:

1 2 3 4 5

在ideone运行:http://ideone.com/pFcrv

嗯,已经有std::copy也可以使用了。

【讨论】:

1.我会根据std::copy 来实现array_fill,因为在许多STL 中会分解为对memcpy 的调用,这在目标硬件上可能更快。 2. 这不适用于 OP 的用例,因为他正在处理多维数组。 @Billy:我也是这么想的。当我在看电视时,我懒得自己实现它:D。这就是我在最后一行提到std::copy 的原因。 array_fill 可以优雅地编写来处理多维数组,std::copy 可能会有很大帮助!【参考方案4】:

您不能(通常)像在 Java 中那样将任意多维数组传递给 C 或 C++ 中的函数(我之所以提到 Java,是因为您的问题历史表明您的经验所在)。

在当前标准中确实没有办法为你的类支持数组初始化器之类的东西,尽管有一些计划在下一个版本 C++0x 中对此进行更改。

如果您希望它具有 Java 数组的灵活性(客户端可以更改指向数组的大小,您有几个选择。第一个也是最好的方法是使用 std::vector&lt;&gt;,它为您实现了一个动态数组,但您可能会受到嵌入式平台的限制。您也可以自己将事物实现为一维数组,并接受动态内存块。示例:

class Foo

    int *theArray_;
    unsigned int rows_;
    unsigned int cols_;
public:
    Foo(int *theArray, int rows, int cols)
        : theArray_(theArray)
        , rows_(rows)
        , cols_(cols)
     
    void UseTheArray()
    
        //Access array[5][6]
        theArray[5*cols+6];
    
;

请注意,在这种情况下,被调用者负责处理内存。还可以考虑使用上面的std::auto_ptr 而不是原始指针,以明确在对象被销毁时谁负责对内存块进行核爆。

另外请注意,您不应该使用名称_x - 以下划线开头的名称附有一大堆规则,您可能不想考虑这些规则。

编辑:这是我原始答案的一部分;错了:

C++ 中的多维数组只是一个内存块。只有在一种情况下才能接受这样的多维数组——在这种情况下,您事先在类中知道数组的确切尺寸。然后你可以这样写:

class Foo 
   int coeff[3][6];
public:
   Foo(int _x[3][6]) : coeff(_x) 
;

但是请注意,数组的大小是固定的,不能由您班级的客户更改。

【讨论】:

“应该”->“不应该”? (下划线还有什么问题?是因为 C++ 名称修改产生的自动化函数假定使用带有前导下划线的标识符命名空间?) 你提到的初始化器:它会自动复制内存,还是使用你传入的内存块? @Billy:这绝对是非法的!我向你们保证!。你传递的参数实际上是一个指向数组的指针,而不是二维数组! @Armen:嗯....我不明白为什么它不起作用。但显然它没有。呸! (有时我想知道为什么多维数组甚至在语言中!) 啊。我尝试了上面你逐字给出的Foo 示例,但我得到了错误:error #776: only "()" is allowed as initializer for array member "Foo::coeff"【参考方案5】:

如果你必须这样做,我只会使用 for 循环迭代二维数组的元素并初始化它们。 或者,如果您追求速度,那么 memset 之类的东西就可以解决问题。

memset(&coeff,0,3*6*sizeof(int)) 

【讨论】:

嗨,比利,对不起,OP 是什么意思? 原帖/原海报【参考方案6】:

你可以这样做:

#include <algorithm>
class Bar 
    
    int coeff[3][6]; 
public:    // what do I do for a constructor???? 
    Bar()
    
        int myCoeffs[3][6] = 
        
              1,  2,  3,  4,  5,  6,    
              7,  8,  9, 10, 11, 12,   
             13, 14, 15, 16, 17, 18
        ; 
        std::swap(coeff, myCoeffs);
    
;

【讨论】:

为什么要交换? coeff = myCoeffs 有什么问题?但这并不能解决 OP 的问题,因为您没有将参数传递给构造函数。 ...但我需要将系数传递给构造函数。否则,对象的每个实例都将获得相同的系数。 @Billy 我(也许为时过早)完全同化了移动语义:)

以上是关于C ++:数组的构造函数/初始化程序?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 数组对复制构造函数和赋值运算符

C++类-手动调用构造函数

C++类-手动调用构造函数

关于C语言结构体构造函数初始化的问题?

构造函数对 const C 字符串数组的帮助

在 C# String 构造函数 String(Char*) 中,为啥构造函数不期望指向字符数组的指针?