自定义数组类:列表初始化的构造方法 [英] Custom Array Class: Constructor for Initialization of List

查看:53
本文介绍了自定义数组类:列表初始化的构造方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用C ++进行自定义数组类的研究(作为一个自我指导的练习),我不确定如何创建一个允许我按照以下方式做一些事情的构造函数:

I'm working on a custom array class in C++ (as a self-led exercise), and I'm not sure how to create a constructor that allows me to do something along the lines of:

#include "array.h"
#include <iostream>
int main()
{
    array<int> test = {1, 2, 3, 4};
    std::cout << test(1) << std::endl;
    return 0;
}

编译器(VS Express 2013)给出的错误是没有构造函数array :: array [with T = int]的实例"与参数列表匹配.参数类型为(int,int,int,int)."

The error that the compiler (VS Express 2013) gives me is "no instance of constructor array::array [with T = int]" matches the argument list. argument types are (int, int, int, int)."

我不确定调用一组元素枚举的构造函数是什么.我知道我已经正确地重载了​​ operator()(const int&).我也知道这(由于我不清楚的原因)有效:

I'm not sure what the constructor that takes the enumeration of a set of elements is called. I know I've properly overloaded operator()(const int&). I also know that this (for a reason that's not clear to me) works:

#include "array.h"
#include <iostream>
int main()
{
    array<char> test = "abcd";
    std::cout << test(1) << std:: endl; // prints 'a', as expected. 
    std::cout << test(4) << std::endl; // prints 'd', as expected.
    return 0;
}

这是通过 array(const T [])构造函数实现的:将为 array< int>解决方案吗?test = {1,2,3,...,n} 的情况是否相似?

This is achieved with a array(const T[]) constructor: will the solution for the array<int> test = {1, 2, 3, ..., n} case be similar?

在此先感谢您的指导.

编辑:如果有帮助,请添加以下代码.

Including the code below, in case it's helpful.

template<typename T>
class array
{
public:
    typedef T* iterator;
    typedef const T* const_iterator;
private:
    iterator head;
    unsigned long elems;
public:
    array()
        : head(nullptr)
        , elems(0) {}
    array(const unsigned long &size)
        : head(size > 0 ? new T[size] : nullptr)
        , elems(size) {}
    array(const T[]);
    array(const array&);
    ~array() { delete[] head; }

    iterator begin() const { return head; }
    iterator end() const { return head != nullptr ? &head[elems] : nullptr; }
    unsigned long size() const { return elems; }

    array& operator=(const array&);
    T& operator()(const unsigned long&);
};

template<typename T>
array<T>::array(const T rhs[])
{
    unsigned long size = sizeof(rhs) / sizeof(T);
    head = new T[size];
    iterator pointer = begin();
    for (const_iterator i = &rhs[0]; i != &rhs[0] + size; i++)
        *pointer++ = *i;
}

template<typename T>
array<T>::array(const array<T> &rhs)
{
    head = new T[rhs.size()];
    iterator pointer = begin();
    for (const_iterator i = rhs.begin(); i != rhs.end(); i++)
        *pointer++ = *i;
}

template<typename T>
array<T>& array<T>::operator=(const array<T> &rhs)
{
    if (this != &rhs)
    {
        delete[] head;
        head = new T[rhs.size()];
        iterator pointer = begin();
        for (const_iterator i = rhs.begin(); i != rhs.end(); i++)
            *pointer++ = *i;
    }
    return *this;
}

template<typename T>
T& array<T>::operator()(const unsigned long &index)
{
    if (index < 1 || index > size())
    {
        // Add some error-handling here.
    }
    return head[index - 1];
}

推荐答案

#include <initializer_list>

// ...

template <typename T>
class array
{   
    // ... 
    array(std::initializer_list<T> il);    

// ...    
template <typename T>
array<T>::array(std::initializer_list<T> il)
{
    unsigned long size = il.size();
    head = new T[size];
    iterator pointer = begin();
    for (const T& i : il)
        *pointer++ = i;
}

// ...
array<int> test = {1, 2, 3, 4};

演示

建议的改进:

  1. array(const T rhs []); 等效于 array(const T * rhs); ,即一个指针,这意味着 sizeof(rhs)/sizeof(T)表达式不会为您提供项目数.如果要为 const char * 使用特殊的构造函数,则考虑整个 array< char> 专业化,或者如果 T,则至少从重载分辨率中禁用此构造函数不是 char

  1. array(const T rhs[]); is an equivalent of array(const T* rhs);, that is, a pointer, which means that sizeof(rhs) / sizeof(T) expression will not give you the number of items. If you want a special constructor for const char*, then consider either an entire array<char> specialization or at least disabling this constructor from the overload resolution if T is not char

head = new T [size]; 默认初始化所有元素(为每个 T 类型的实例调用默认构造函数).然后调用一个赋值操作: * pointer ++ = * i; .这可以通过使用 placement-new 来改进,例如 :: new((void *)ptr)T(* i); 其中 ptr 是指向未初始化的原始内存缓冲区的指针,例如 new char [sizeof(T)* size] 或从

head = new T[size]; default-initializes all elements (calls default constructor for each instance of type T). Then you call an assignment operation: *pointer++ = *i;. This can be improved by utilizing a placement-new, like ::new ((void*)ptr) T(*i); where ptr is a pointer to a raw, uninitialized memory buffer, like new char[sizeof(T)*size] or returned from get_temporary_buffer.


如果您想知道为什么下面的方法有效 array< char>test = {"abcd"}; 您当前的实现,这是一个解释:


And if you are wondering why the following works array<char> test = { "abcd" }; with your current implementation then here is an explanation:

  1. array< T> 类具有一个构造函数,该构造函数采用 const T [] ,对于 T = char ,其实例化为 array< char> :: array(const char *).

  1. array<T> class has a constructor taking const T[], which for T=char is instantiated as array<char>::array(const char*).

列表初始化可用于调用对象的构造函数.

List-initialization can be used to call object's constructor.

您的 const T [] 构造函数不是显式的,这意味着您可以使用 copy-initialization 语法,如下所示:

Your const T[] constructor is not explicit, which means that you can use copy-initialization syntax like below:

array<char> test = { "test" };

  • 对于 T = char ,表达式 sizeof(rhs)/sizeof(T)尽管如上所述无效,但其计算结果为 sizeof(char *)/sizeof(char),(最有可能是 4/1 = 4 .

  • The expression sizeof(rhs) / sizeof(T), although not valid as explained above, for T=char evaluates to sizeof(char*) / sizeof(char), which is (most-probably) 4 / 1 = 4.

    用于初始化的"test" 恰好有4个字母,这很幸运.

    Your "test" used for initialization has exactly 4 letters, your luck.

    这篇关于自定义数组类:列表初始化的构造方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆