it-swarm.asia

لماذا لا يحتوي std :: array على مُنشئ يأخذ قيمة للصفيف المراد ملؤه؟

هو غياب

std::array<T,size>::array(const T& value);

سهو؟ يبدو الأمر مفيدًا لي ، والحاويات الديناميكية (مثل std::vector) لها مُنشئ مماثل.

أنا أدرك تماما

std::array<T,size>::fill(const T& value);

ولكن هذا ليس مُنشئًا ، وسيتم التخلص من الذاكرة أولاً. ماذا لو كنت أريد جميع -1 مثل هذا الرجل ؟

66
rubenvb

std::array هي ، حسب التصميم ، مجمعة ، لذلك لا يوجد مُنشئون مُعلَن من قِبل المستخدم.

كما تقول ، يمكنك استخدام fill بعد الإنشاء الافتراضي. نظرًا لأنها مجمعة ، لن تؤدي البنية الافتراضية إلى تهدئة الذاكرة ، ولكنها ستتركها غير مهيأة (إذا كان النوع المضمن قابلاً للتهيئة بشكل تافه).

49
Mike Seymour

لاحظ أنه يمكنك محاكاة هذا النوع من المنشئات بكفاءة من خلال الاستفادة من حقيقة أن الصفيف لا يتم تهيئته صفر ، وله مُنشئ نسخ ويفعله.

template <size_t N, class T>
array<T,N> make_array(const T &v) {
    array<T,N> ret;
    ret.fill(v);
    return ret;
}

auto a = make_array<20>('z');
21
tohava

بادئ ذي بدء ، إنه ليس std::array<T> ، إنه std::array<T,N> حيث N عبارة عن وقت متكامل للتعبير الثابت.

ثانياً ، std::array يتم تجميعه حسب التصميم. لذلك لا يحتوي على أي شيء يجعله غير مجمع ، وهذا هو السبب في أنه لا يحتوي على مُنشئ ... ومدمّر ، وظائف افتراضية ، إلخ.

11
Nawaz

يمكنك استخدام std::index sequence لذلك:

namespace detail
{

    template <typename T, std::size_t...Is>
    constexpr std::array<T, sizeof...(Is)>
    make_array(const T& value, std::index_sequence<Is...>)
    {
        return {{(static_cast<void>(Is), value)...}};
    }
}

template <std::size_t N, typename T>
constexpr std::array<T, N> make_array(const T& value)
{
    return detail::make_array(value, std::make_index_sequence<N>());
}

عرض توضيحي

std::make_index_sequence هو C++ 14 ، ولكن يمكن تنفيذه في C++ 11.

static_cast<void>(Is) هي التعامل مع operator, الشرير الذي قد يوفره T.

9
Jarod42