Нет, это не рекомендуется.То, как вы предлагаете, не является исключительной безопасностью и несовместимо с const
или подобъектами, которые требуют построения не по умолчанию.
Вместо этого используйте ctor-initializer-list .Повторное использование кода может быть достигнуто с помощью статических вспомогательных функций, вызываемых в ctor-initializer-list , или путем перемещения логики в конструкторы подобъектов.
Для выделения памяти используйте подобъект на ресурс.Логика управления памятью заканчивается в конструкторе и деструкторе подобъекта.Во многих случаях вы можете использовать существующие классы RAII из библиотеки, такие как std::vector
, и вам не нужно самостоятельно писать какой-либо код управления памятью.
Большинство операторов могут повторно использовать логику в конструкторах, используя идиома копирования и замены .
РЕДАКТИРОВАТЬ: Конструкция, исключающая исключительные ситуации, может выглядеть примерно так:
#include <vector>
template<typename T>
class matrix
{
int m_nCols;
std::vector<T*> m_rows;
std::vector<T> m_cells;
size_t makeIndex( int row, int col ) const { return row*m_nCols + col; }
public:
matrix( int nRows, int nCols )
: m_nCols(nCols), m_rows(nRows), m_cells(nRows * nCols)
{
while (nRows--) m_rows[nRows] = &m_cells[nRows * nCols];
}
matrix( const matrix<T>& other )
: m_nCols(other.m_nCols), m_rows(other.m_rows.size()), m_cells(other.m_cells)
{
int nRows = other.m_rows.size();
while (nRows--) m_rows[nRows] = &m_cells[nRows * nCols];
}
void swap( matrix& other )
{
using std::swap;
swap(m_nCols, other.m_nCols);
swap(m_rows, other.m_rows);
swap(m_cells, other.m_cells);
}
matrix& operator=( matrix other )
{
other.swap(*this);
return *this;
}
const T& operator()( int row, int col ) const { return m_cells[makeIndex(row,col)]; }
T& operator()( int row, int col ) { return m_cells[makeIndex(row,col)]; }
};
Деструктор std::vector
позаботится об освобождениипамяти, и поскольку эти два выделения являются отдельными объектами, если m_cells
не сможет выделить свою память, деструктор для m_rows
запустится, и ничего не просочится.
Конечно, std::vector
немногоИзлишне здесь, массив RAII фиксированного размера будет достаточно.Но std::auto_ptr
нельзя использовать с массивами.Я думаю, что C ++ 0x должен добавить стандартный массив массивов RAII фиксированного размера.
РЕДАКТИРОВАТЬ: По запросу, 3-D версия:
#include <vector>
template<typename T>
class cube
{
int m_nCols, m_nRows;
std::vector<T> m_cells;
size_t makeIndex( int row, int col, int channel ) const { return (channel*m_nRows + row)*m_nCols + col; }
public:
cube( int nRows, int nCols, int nChannels )
: m_nCols(nCols), m_nRows(nRows), m_cells(nRows * nCols * nChannels)
{
}
cube( const cube<T>& other )
: m_nCols(other.m_nCols), m_nRows(other.m_nRows), m_cells(other.m_cells)
{
}
void swap( cube& other )
{
using std::swap;
swap(m_nCols, other.m_nCols);
swap(m_nRows, other.m_nRows);
swap(m_cells, other.m_cells);
}
cube& operator=( cube other )
{
other.swap(*this);
return *this;
}
const T& operator()( int row, int col, int channel ) const { return m_cells[makeIndex(row,col,channel)]; }
T& operator()( int row, int col, int channel ) { return m_cells[makeIndex(row,col,channel)]; }
class channel_iterator
{
cube& const cube;
int const row, col;
int channel;
friend class cube;
channel_iterator( cube& all, int r, int c, int n ) : cube(all), row(r), col(c), channel(n) {}
public:
T& operator*() const { return cube(row, col, channel); }
channel_iterator& operator++() { ++channel; return *this; }
channel_iterator operator++(int) { return channel_iterator(cube, row, col, channel++); }
bool operator!=(const channel_iterator& other) const { assert(&cube == &other.cube); return (row == other.row && col == other.col && channel == other.channel); }
};
int channel_count() const { return m_cells.size() / m_nRows / m_nChannels; }
pair<channel_iterator, channel_iterator> range(int row, int col) { return make_pair(channel_iterator(*this, row, col, 0), channel_iterator(*this, row, col, channel_count())); }
};