C++:数组的构造函数初始值设定项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2409819/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 23:24:15  来源:igfitidea点击:

C++: constructor initializer for arrays

c++constructorinitializer

提问by Jason S

I'm having a brain cramp... how do I initialize an array of objects properly in C++?

我脑抽筋了...如何在 C++ 中正确初始化对象数组?

non-array example:

非数组示例:

struct Foo { Foo(int x) { /* ... */  } };

struct Bar { 
     Foo foo;

     Bar() : foo(4) {}
};

array example:

数组示例:

struct Foo { Foo(int x) { /* ... */  } };

struct Baz { 
     Foo foo[3];

     // ??? I know the following syntax is wrong, but what's correct?
     Baz() : foo[0](4), foo[1](5), foo[2](6) {}
};

edit:Wild & crazy workaround ideas are appreciated, but they won't help me in my case. I'm working on an embedded processor where std::vector and other STL constructs are not available, and the obvious workaround is to make a default constructor and have an explicit init()method that can be called after construction-time, so that I don't have to use initializers at all. (This is one of those cases where I've gotten spoiled by Java's finalkeyword + flexibility with constructors.)

编辑:狂野和疯狂的解决方法的想法很受欢迎,但在我的情况下它们对我没有帮助。我正在开发一个嵌入式处理器,其中 std::vector 和其他 STL 构造不可用,明显的解决方法是创建一个默认构造函数并具有一个init()可以在构造时调用的显式方法,这样我就不会根本不必使用初始化程序。(这是我被 Java 的final关键字 + 构造函数的灵活性所宠坏的情况之一。)

采纳答案by AProgrammer

There is no way. You need a default constructor for array members and it will be called, afterwards, you can do any initialization you want in the constructor.

不可能。您需要一个数组成员的默认构造函数,它将被调用,之后,您可以在构造函数中进行任何您想要的初始化。

回答by Barry

Just to update this question for C++11, this is now both possible to do and very natural:

只是为了更新 C++11 的这个问题,现在这既可以做又很自然:

struct Foo { Foo(int x) { /* ... */  } };

struct Baz { 
     Foo foo[3];

     Baz() : foo{{4}, {5}, {6}} { }
};

Those braces can also be elided for an even more concise:

为了更简洁,也可以省略这些大括号:

struct Baz { 
     Foo foo[3];

     Baz() : foo{4, 5, 6} { }
};

Which can easily be extended to multi-dimensional arrays too:

这也可以很容易地扩展到多维数组:

struct Baz {
    Foo foo[3][2];

    Baz() : foo{1, 2, 3, 4, 5, 6} { }
};

回答by Michael Kristofik

Right now, you can't use the initializer list for array members. You're stuck doing it the hard way.

现在,您不能将初始化列表用于数组成员。你被困在艰难的道路上。

class Baz {
    Foo foo[3];

    Baz() {
        foo[0] = Foo(4);
        foo[1] = Foo(5);
        foo[2] = Foo(6);
    }
};

In C++0x you can write:

在 C++0x 中,你可以这样写:

class Baz {
    Foo foo[3];

    Baz() : foo({4, 5, 6}) {}
};

回答by UncleBens

Unfortunately there is no way to initialize array members till C++0x.

不幸的是,在 C++0x 之前无法初始化数组成员。

You could use a std::vector and push_back the Foo instances in the constructor body.

您可以在构造函数体中使用 std::vector 和 push_back Foo 实例。

You could give Foo a default constructor (might be private and making Baz a friend).

你可以给 Foo 一个默认构造函数(可能是私有的,让 Baz 成为朋友)。

You could use an array object that iscopyable (boost or std::tr1) and initialize from a static array:

您可以使用复制的数组对象(boost 或 std::tr1)并从静态数组初始化:

#include <boost/array.hpp>

struct Baz {

    boost::array<Foo, 3> foo;
    static boost::array<Foo, 3> initFoo;
    Baz() : foo(initFoo)
    {

    }
};

boost::array<Foo, 3> Baz::initFoo = { 4, 5, 6 };

回答by Nordl?w

You can use C++0xautokeyword together with template specializationon for example a function named boost::make_array()(similar to make_pair()). For the case of where Nis either 1 or 2 arguments we can then write variant Aas

您可以将C++0xauto关键字与模板特化一起用于例如名为boost::make_array()(类似于make_pair())的函数。对于 whereN是 1 或 2 个参数的情况,我们可以将变体 A写为

namespace boost
{
/*! Construct Array from @p a. */
template <typename T>
boost::array<T,1> make_array(const T & a)
{
    return boost::array<T,2> ({{ a }});
}
/*! Construct Array from @p a, @p b. */
template <typename T>
boost::array<T,2> make_array(const T & a, const T & b)
{
    return boost::array<T,2> ({{ a, b }});
}
}

and variant Bas

变体 B

namespace boost {
/*! Construct Array from @p a. */
template <typename T>
boost::array<T,1> make_array(const T & a)
{
    boost::array<T,1> x;
    x[0] = a;
    return x;
}
/*! Construct Array from @p a, @p b. */
template <typename T>
boost::array<T,2> make_array(const T & a, const T & b)
{
    boost::array<T,2> x;
    x[0] = a;
    x[1] = b;
    return x;
}
}

GCC-4.6 with -std=gnu++0xand -O3generates the exact same binary codefor

GCC-4.6与-std=gnu++0x-O3产生完全相同的二进制代码

auto x = boost::make_array(1,2);

using both Aand Bas it does for

同时使用因为它为

boost::array<int, 2> x = {{1,2}};

For user defined types(UDT), though, variant B results in an extra copy constructor, which usually slow things down, and should therefore be avoided.

但是,对于用户定义类型(UDT),变体 B 会导致额外的复制构造函数,这通常会减慢速度,因此应该避免。

Note that boost::make_arrayerrors when calling it with explicit char array literals as in the following case

请注意,boost::make_array使用显式字符数组文字调用它时会出现错误,如下例所示

auto x = boost::make_array("a","b");

I believe this is a good thing as const char*literals can be deceptivein their use.

我相信这是一件好事,因为const char*文字在使用中可能具有欺骗性

Variadic templates, available in GCC since 4.5, can further be used reduce all template specialization boiler-plate code for each Ninto a single template definitionof boost::make_array()defined as

可变参数模板,在GCC可用自4.5,还可以用于减少每个所有模板特锅炉板代码N到一个单一的模板定义boost::make_array()定义为

/*! Construct Array from @p a, @p b. */
template <typename T, typename ... R>
boost::array<T,1+sizeof...(R)> make_array(T a, const R & ... b)
{
    return boost::array<T,1+sizeof...(R)>({{ a, b... }});
}

This works pretty much as we expect. The first argument determines boost::arraytemplate argument Tand all other arguments gets converted into T. For some cases this may undesirable, but I'm not sure how if this is possible to specify using variadic templates.

这与我们预期的差不多。第一个参数确定boost::array模板参数T,所有其他参数都转换为T. 在某些情况下,这可能是不可取的,但我不确定如何使用可变参数模板进行指定。

Perhaps boost::make_array()should go into the Boost Libraries?

也许boost::make_array()应该进入 Boost 库?

回答by Steve Jessop

This seems to work, but I'm not convinced it's right:

这似乎有效,但我不相信这是正确的:

#include <iostream>

struct Foo { int x; Foo(int x): x(x) { } };

struct Baz { 
     Foo foo[3];

    static int bar[3];
     // Hmm...
     Baz() : foo(bar) {}
};

int Baz::bar[3] = {4, 5, 6};

int main() {
    Baz z;
    std::cout << z.foo[1].x << "\n";
}

Output:

输出:

$ make arrayinit -B CXXFLAGS=-pedantic && ./arrayinit
g++ -pedantic    arrayinit.cpp   -o arrayinit
5

Caveat emptor.

买者自负。

Edit: nope, Comeau rejects it.

编辑:不,科莫拒绝了。

Another edit: This is kind of cheating, it just pushes the member-by-member array initialization to a different place. So it still requires Foo to have a default constructor, but if you don't have std::vectorthen you can implement for yourself the absolute bare minimum you need:

另一个编辑:这是一种作弊,它只是将逐个成员的数组初始化推送到不同的地方。所以它仍然需要 Foo 有一个默认的构造函数,但如果你没有,std::vector那么你可以为自己实现你需要的绝对最低限度:

#include <iostream>

struct Foo { 
    int x; 
    Foo(int x): x(x) { }; 
    Foo(){}
};

// very stripped-down replacement for vector
struct Three { 
    Foo data[3]; 
    Three(int d0, int d1, int d2) {
        data[0] = d0;
        data[1] = d1;
        data[2] = d2;
    }
    Foo &operator[](int idx) { return data[idx]; }
    const Foo &operator[](int idx) const { return data[idx]; }
};

struct Baz { 
    Three foo;

    static Three bar;
    // construct foo using the copy ctor of Three with bar as parameter.
    Baz() : foo(bar) {}
    // or get rid of "bar" entirely and do this
    Baz(bool) : foo(4,5,6) {}
};

Three Baz::bar(4,5,6);

int main() {
    Baz z;
    std::cout << z.foo[1].x << "\n";
}

z.fooisn't actually an array, but it looks about as much like one as a vector does. Adding begin()and end()functions to Three is trivial.

z.foo实际上不是一个数组,但它看起来和向量一样。向三添加begin()end()函数是微不足道的。

回答by AnT

In the specific case when the array is a data member of the class you can'tinitialize it in the current version of the language. There's no syntax for that. Either provide a default constructor for array elements or use std::vector.

在特定情况下,当数组是类的数据成员时,您无法在当前版本的语言中对其进行初始化。没有语法。要么为数组元素提供默认构造函数,要么使用std::vector.

A standalone array can be initialized with aggregate initializer

可以使用聚合初始化程序初始化独立数组

Foo foo[3] = { 4, 5, 6 };

but unfortunately there's no corresponding syntax for the constructor initializer list.

但不幸的是,构造函数初始值设定项列表没有相应的语法。

回答by Robert

Only the default constructor can be called when creating objects in an array.

在数组中创建对象时只能调用默认构造函数。

回答by John Dibling

There is no array-construction syntax that ca be used in this context, at least not directly. You can accomplish what you're trying to accomplish by something along the lines of:

没有可以在此上下文中使用的数组构造语法,至少不能直接使用。您可以通过以下方式完成您想要完成的工作:

Bar::Bar()
{
    static const int inits [] = {4,5,6};
    static const size_t numInits = sizeof(inits)/sizeof(inits[0]);
    std::copy(&inits[0],&inits[numInits],foo);  // be careful that there are enough slots in foo
}

...but you'll need to give Foo a default constructor.

...但你需要给 Foo 一个默认的构造函数。

回答by the100rabh

Ideas from a twisted mind :

来自扭曲思想的想法:

class mytwistedclass{
static std::vector<int> initVector;
mytwistedclass()
{
    //initialise with initVector[0] and then delete it :-)
}

};

now set this initVectorto something u want to before u instantiate an object. Then your objects are initialized with your parameters.

现在initVector在实例化对象之前将其设置为您想要的内容。然后你的对象用你的参数初始化。