Шаблон и распределение памяти - PullRequest
2 голосов
/ 01 апреля 2011
#include <iostream>

template<class T> T CreateArray(T a, int n)
{
    a = new T [n]; // mistake: double* = double**
    return a;
}

int main()
{
    double* a;
    int n = 5;
    a = CreateArray(a,n);
    return 0;
}

можно ли выделить память используя шаблон и новый? И в чем моя ошибка?

Ответы [ 4 ]

3 голосов
/ 01 апреля 2011

Итак, другие объяснили, почему ваш код не работает и как его можно улучшить.

Теперь я покажу, как вы можете все же получить следующий код для компиляции - идля правильной работы:

 double* a = CreateArray(5);
 int* b = CreateArray(7);

Проблема, как уже упоминалось, заключается в том, что C ++ не выводит аргументы шаблона из одних только возвращаемых типов.

Вы можете обойти это ограничение, вернув вышеуказанную функцию возвратапростой прокси-объект.Прокси-объект выполняет одну операцию: (неявное) преобразование в T*.Вот где происходит фактическое распределение.

Поэтому функция CreateArray очень проста (и не шаблон):

CreateArrayProxy CreateArray(std::size_t num_elements) {
    return CreateArrayProxy(num_elements);
}

Что касается прокси:

struct CreateArrayProxy {
    std::size_t num_elements;

    CreateArrayProxy(std::size_t num_elements) : num_elements(num_elements) { }

    template <typename T>
    operator T*() const {
        return new T[num_elements];
    }
};

Easy as π.

Теперь, стоит ли использовать этот код?Нет, наверное нет.Это не дает реального преимущества перед прямым распределением.Но это полезная идиома, чтобы знать.

3 голосов
/ 01 апреля 2011

Ваш код содержит некоторые неправильные вещи.Во-первых, вы можете сделать что-то вроде того, что вы пытаетесь сделать, но вы должны написать что-то вроде этого:

template<class T> T* CreateArray(int n)
{
    T* a = new T [n];
    return a;
}

int main()
{
    double* a;
    int n = 5;
    a = CreateArray<double>(n);
    return 0;
}

Обратите внимание, что вам не нужно передавать массив a (это будетскопировано внутрь CreateArray, и его изменения не будут видны внутри main).Также обратите внимание, что вы определяете шаблон для возврата указателя T*, именно этого ожидает main() a.

2 голосов
/ 01 апреля 2011

Я предпочитаю оставлять пустыми указатели значения NULL.

#include <iostream>

template<class T> bool CreateArray(T * &a, int n)
{
    if ( a != 0 )
      return false;
    a = new T [n];
    return true;
}

int main()
{
    double* a = 0;
    int n = 5;
    CreateArray(a,n);
    return 0;
}

vector тоже может быть хорошим решением. Я думаю, что это лучше, потому что вы не будете делать утечки памяти.

#include <vector>

int main()
{
    std::vector<double> a;
    int n = 5;
    a.resize(n);
    return 0;
}
2 голосов
/ 01 апреля 2011

Вы хотите принять указатель на тип, который хотите выделить:

template<class T> T* CreateArray(T* a, int n)
{
    a = new T [n];
    return a;
}

Это должно сработать.

...