2014-10-04 2 views
5

У меня есть класс, который должен хранить массив с переменным размером. В идеале этот размер будет определяться как параметр, предоставляемый конструктору класса.Как инициализировать массив переменных размера в классе C++?

можно определить константу, а затем работать с этим, как показано ниже:

#include <iostream> 
#define ARRSIZE 5 

class Classy{ 
    private: 
     int myarray[ARRSIZE]; 

    public: 
     Classy(); 
     void printarray(); 
}; 

Classy::Classy(){ 
    for(int i = 0; i < ARRSIZE; i++){ 
     myarray[i] = i * i * 2; 
    } 
} 

void Classy::printarray(){ 
    for(int i = 0; i < ARRSIZE; i++){ 
     std::cout << myarray[i] << std::endl; 
    } 
} 

Однако, я хотел бы сделать это следующим образом:

#include <iostream> 
class Classy{ 
    private: 
     int arraysize; 
     int myarray[arraysize]; 

    public: 
     Classy(int parraysize); 
     void printarray(); 
}; 

Classy::Classy(int parraysize){ 
    arraysize = parraysize; 
    for(int i = 0; i < arraysize; i++){ 
     myarray[i] = i * i * 2; 
    } 
} 

void Classy::printarray(){ 
    for(int i = 0; i < arraysize; i++){ 
     std::cout << myarray[i] << std::endl; 
    } 
} 

Компилятор действительно Безразлично» Мне нравится мой подход, поэтому я ищу альтернативный способ делать вещи.

Я сделал некоторые поисковые запросы по этому вопросу, но мои поиски не принесли результатов. Я нашел this подход, который использует динамическое распределение памяти. Этого я бы хотел избежать, поэтому я ищу решение, которое не полагается на это. Может быть (и я начинаю думать), что это единственное изящное решение моей проблемы (и если это так, вопрос, конечно, должен быть закрыт как дубликат).

+6

Используйте ['std :: vector'] (http://en.cppreference.com/w/cpp/container/vector). –

+0

Я не большой поклонник массивов в целом, для большинства целей.Если вы действительно не нуждаетесь в них для некоторой воспринимаемой оптимизации, 'std :: vector' является вашим другом и, скорее всего, сгибается с вашими требованиями. Но вы можете использовать [std :: array] (http://en.cppreference.com/w/cpp/container/array) ... удобную альтернативу C++ для C-массивов. – HostileFork

+6

@HostileFork: 'std :: array' не является переменным размером. 'std :: unique_ptr ' является стандартным компонентом для массива с размером, заданным при построении. 'std :: vector ' для массива, размер которого может меняться в течение всего срока его службы. –

ответ

9

Необходимо использовать динамическое распределение, потому что sizeof (Classy) должно быть константой времени компиляции. Невозможно увеличить внутренний размер объекта. Но динамическое распределение не должно быть таким сложным, как предполагает эта ссылка.

Вы можете сделать это следующим образом:

#include <memory> 
class Classy 
{ 
    private: 
     int arraysize; 
     std::unique_ptr<int[]> myarray; 

    public: 
     Classy(int parraysize); 
     void printarray(); 
}; 

Classy::Classy(int parraysize) 
    : arraysize{parraysize} 
    , myarray{new int[arraysize]} 
{ 
    for(int i = 0; i < arraysize; i++){ 
     myarray[i] = i * i * 2; 
    } 
} 

#include <iostream> 
void Classy::printarray() 
{ 
    for(int i = 0; i < arraysize; i++){ 
     std::cout << myarray[i] << std::endl; 
    } 
} 

Это позволит размер меняться в момент создания, и быть закреплен в дальнейшем. std::unique_ptr позаботится о том, чтобы автоматически уничтожить содержимое массива, когда ваш объект умирает.

1

Вы хотите использовать шаблоны, чтобы решить эту проблему:

#include <array> 

template<std::size_t ArraySize> 
class Classy final 
{ 
public: 
    static const std::size_t size = ArraySize; 

    /* The rest of your public interface here */ 
private: 
    std::array<int, ArraySize> m_array; 
}; 

Затем вы можете использовать свой класс, как это:

int main() 
{ 
    Classy<5> hasArrayOfFiveElements; 
    return 0; 
} 

Вы могли бы очень хорошо выбирать не использовать зЬй :: массив, в предпочтении для массива c-style. Но мы пишем C++, поэтому давайте использовать лучшие языковые возможности, которые у нас есть для нас:

+3

Это не позволяет вам «передать размер конструктору», как того требует вопрос. –

2

Вам необходимо динамически выделять массив, используя new[], а затем delete[] это в вашем деструкторе. В качестве альтернативы используйте std::vector<int> и reserve сумму, переданную конструктору. Тем не менее, еще один способ состоит в том, чтобы сделать ваш шаблон шаблоном, принимая аргумент size_t для количества элементов, которые вы хотите, но это полностью удаляет его динамический аспект (и вы также можете использовать std::array в этой точке.

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

3

Ну, я думаю, что вы не можете сделать он не использует динамическое распределение памяти при использовании классического массива, но вы можете использовать std :: vector. Вы можете сделать это следующим образом:

#include <iostream> 
class Classy{ 
    private: 
     int arraysize; 
     std::vector<int> myArrayOfInts; 

    public: 
     Classy(int parraysize); 
     void printarray(); 
}; 

Classy::Classy(int parraysize){ 
    arraysize = parraysize; 
    for(int i = 0; i < arraysize; i++){ 
     myArrayOfInts.push_back(i * i * 2); 
    } 
} 

void Classy::printarray(){ 
    for(int i = 0; i < myArrayOfInts.size(); i++){ //you could also use arraysize, but then you 
     std::cout << myArrayOfInts[i] << std::endl;//must update it when you add or remove any 
    }            // element from vector 
} 
+0

'std :: vector' нужен тип –

+0

да, конечно, я забыл написать его: D спасибо, я его обновил. –

+0

Почему вы отслеживаете размер 'std :: vector' с' int arraysize; '? Не можете ли вы использовать метод 'size()' вектора? – Galik

Смежные вопросы