Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 18.03.2012, 10:39   #1
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию Массивы-данные члены

Итак, есть класс, принимающий на входе массив. При этом нужно выполнить его глубокое копирование. Вопрос: куда можно скопировать данные?

Требования к задаче:
1. Работа со стеком (никакой кучи)
2. Каждый объект класса должен получить собственную копию массива

Пример:

Код:
template<class tType>
class TPtrArray
{
public:
    TPtrArray():mPtrArray(0l), mNumberOfElement(0){}

    template<class tSrc, size_t tNum>
    TPtrArray(tSrc (&src)[tNum]) { mPtrArray = src;  mNumberOfElement = tNum; }
public:
    size_t GetNumOfElements()const { return mNumberOfElement;}
    size_t GetSize()const { return mNumberOfElement*sizeof(tType);}
    tType& operator[](size_t index)  {   return *(mPtrArray+index);  }
private:
    tType* mPtrArray;
    size_t mNumberOfElement;
};
Представленный класс указателей на обычные массивы не умеет выполнять глубокое копирование данных.

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


зы: соль затеи в том, что бы научить класс "статических массивов" пересоздаваться с новым размером. Что бы можно было выполнять следующее:

int A[10];
int B[20];

TArray<int> test(A); //сделал глубокое копирование, и хранит внутри массив из 10 элементов

TArray<int> test = B; //сделал глубокое копирование, и хранит внутри массив из 20 элементов

И никакой кучи.
_Bers вне форума Ответить с цитированием
Старый 18.03.2012, 22:21   #2
pproger
C++ hater
Старожил
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

Цитата:
соль затеи в том, что бы научить класс "статических массивов" пересоздаваться с новым размером
Код:
int A[10];
int B[20];

TArray<int> test(A); //сделал глубокое копирование, и хранит внутри массив из 10 элементов

TArray<int> test = B; //сделал глубокое копирование, и хранит внутри массив из 20 элементов
где тут "пересоздавание"? если это написано в одном скопе - ошибка. если в разных - то получим два разных объекта
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance
pproger вне форума Ответить с цитированием
Старый 18.03.2012, 22:33   #3
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

что такое "скоп"?
_Bers вне форума Ответить с цитированием
Старый 18.03.2012, 22:37   #4
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

ааа... ну блин, опечатался:

Код:
int A[10];
int B[20];

TArray<int> test(A); //сделал глубокое копирование, и хранит внутри массив из 10 элементов

test = B; //сделал глубокое копирование, и хранит внутри массив из 20 элементов
_Bers вне форума Ответить с цитированием
Старый 18.03.2012, 22:46   #5
pproger
C++ hater
Старожил
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

область видимости.
если считать, что класс реализован, я не пойму в твоем примере, где тут "пересоздавание"?
если напишем
Код:
{
int A[10];
int B[20];

TArray<int> test(A);
TArray<int> test = B;
}
если напишем
Код:
{
int A[10];
int B[20];

TArray<int> test(A);

{
TArray<int> test = B;
}
}
то получим два разных объекта.

обобщу мой вопрос. что такое ПЕРЕСОЗДАВАНИЕ, и чем тебя не устроило например это?
Код:
template <typename T, size_t size>
class StaticArray {
public:
	StaticArray()
	{
		for (size_t i = 0; i < size; i++)
			m_array[i] = 0;
	}

	StaticArray(const T (&arr)[size])
	{
		for (size_t i = 0; i < size; i++)
			m_array[i] = arr[i];
	}

	size_t length() const
	{ return sizeof(m_array) / sizeof(m_array[0]); }

private:
	T m_array[size];
};
Код:
StaticArray<int, 100> arr; //пустой статический массив

int A[100];
int B[200];

StaticArray<int, 100> arr1(A);
StaticArray<int, 200> arr2 = B;
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance
pproger вне форума Ответить с цитированием
Старый 18.03.2012, 22:50   #6
pproger
C++ hater
Старожил
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

2_Bers
Цитата:
ааа... ну блин, опечатался

TArray<int> test(A); //сделал глубокое копирование, и хранит внутри массив из 10 элементов

test = B; //сделал глубокое копирование, и хранит внутри массив из 20 элементов
именно так на стеке не получится. только как я показал. и то, присваивать можно только классу такого же типа (с одинаковым типом элемента массива и одинаковым размером массива)
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance
pproger вне форума Ответить с цитированием
Старый 19.03.2012, 07:36   #7
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Гм... в общем, мыслю я, любая работа с кучей тут будет более эффективная, нежели огород из шаблонов.

Даже если и получится нечто - вряд ли оно будет практично.

А покамест нерабочий вариант таков:

Код:
#include "TPtrArray.h"

template<class tType>
class TArray
{
public:
    template<class T, size_t N>   TArray& operator=(T (&arr)[N]) 
    { 
        //константная ссылка продлевает жизнь временного объекта
        const T (&cnst)[N] =  Create(arr); 
        
        //но с константным массивом много каши не сваришь

        //здесь компилятор фиксит,факт потери константности ссылки на временный объект
        //И уничтожает его.
        T (&tmp)[N] = const_cast<T (&)[N]>(cnst); 
        
        //В итоге указатель на простой массив содержит мусор
        mArray = tmp; return *this; 
    }
public:
    //Создаем массив, и возвращаем его по ссылке
    template<class T, size_t N>
    T (&Create(  T (&arr)[N] )   )[N]
    {
        T tmp[N]; for(size_t i=0;i<N;++i ) { tmp[i]= arr[i]; }
        return tmp; 
    }
private:
    TPtrArray<tType> mArray;
};
Идея может быть в том, что бы создавать временный объект, и продлевать его время жизни за счет константной ссылки.

При этом, такой "массив" можно будет использовать только как временный приемник данных. Он сможет принять данные, и попридержать их, пока они не будут скопированы куда либо вызывающей стороной. После чего, временный объект можно будет спокойно уничтожить.

Предполагаю - даже если получится, то решение будет сложным, шаблонным, и не гибким. А посему поделка не взлетит...

Можно ещё хранить данные в качестве static локальных массивов. Но такая жесть приведет к усложнению поделки до безобразия: один статик массив на все объекты класса. К тому же, каждый очередной массив уникальной размерности будет приводить к разрастанию кода инстанцированного класса, и замедлять компиляцию.

Последний раз редактировалось _Bers; 19.03.2012 в 07:41.
_Bers вне форума Ответить с цитированием
Старый 19.03.2012, 17:53   #8
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
Код:
        //константная ссылка продлевает жизнь временного объекта
        const T (&cnst)[N] =  Create(arr); 
        
        //но с константным массивом много каши не сваришь

        //здесь компилятор фиксит,факт потери константности ссылки на временный объект
        //И уничтожает его.
        T (&tmp)[N] = const_cast<T (&)[N]>(cnst);
Глупости, в C++ нет ни уборщика мусора, ни автоматического подсчёта ссылок, потому никакие константные ссылки не спасут локальные данные функции от уничтожения.
А вообще, не понятно в чём затея этого дела. Если массивы фиксированной длины, то почему не воспользоваться тем кодом, что привёл pproger, но с дополнительным свойством, определяющим текущий размер массива и перегруженным оператором присваивания. Сам массив выделять с запасом.
Код:
  StaticArray<int, 200> arr; // выделили 200 элементов, сюда влезет и a и b
  int a[100], b[150];
  arr = a;
  std::cout << arr.capacity() << std::endl; // 200
  std::cout << arr.size() << std::endl; // 100
  arr = b;
netrino вне форума Ответить с цитированием
Старый 19.03.2012, 22:04   #9
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от netrino Посмотреть сообщение
Глупости, в C++ нет ни уборщика мусора, ни автоматического подсчёта ссылок, потому никакие константные ссылки не спасут локальные данные функции от уничтожения.
По стандарту, пока жива константная ссылка на временный объект, этот объект будет жив.
Есть любопытное обсуждение этого явления из области "когда мальчики тупят, им на помощь приходят девочки"
http://alenacpp.blogspot.com/2008/01/const.html

Цитата:
Сообщение от netrino Посмотреть сообщение
А вообще, не понятно в чём затея этого дела. Если массивы фиксированной длины...
Принимающая сторона не делает предположений о размере получаемого массива.

Это значит, что принимающая сторона принимает объект, который будет инкапсулировать внутри себя эту информацию.

При этом важно, что бы пришедшие данные были скопированы, и стали уникальной собственностью принимающей стороны (а не просто указатель на внешние данные).

Последний раз редактировалось _Bers; 19.03.2012 в 22:11.
_Bers вне форума Ответить с цитированием
Старый 21.03.2012, 19:40   #10
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
По стандарту, пока жива константная ссылка на временный объект, этот объект будет жив.
Не знал, круто. Только содержимое массива всё равно будет уничтожено после выхода из функции.
И кстати, "фиксим константность" не сработает, так как в области видимости всё ещё остаётся константная ссылка и данные будут уничтожены только по выходу из текущей области видимости.
Цитата:
Сообщение от _Bers Посмотреть сообщение
Есть любопытное обсуждение этого явления из области "когда мальчики тупят, им на помощь приходят девочки"
http://alenacpp.blogspot.com/2008/01/const.html
При чём здесь "девочки", когда по ссылке перевод статьи Герба Саттера?)

Цитата:
Сообщение от _Bers Посмотреть сообщение
Принимающая сторона не делает предположений о размере получаемого массива.

Это значит, что принимающая сторона принимает объект, который будет инкапсулировать внутри себя эту информацию.

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

Последний раз редактировалось netrino; 21.03.2012 в 19:48.
netrino вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Данные-члены шаблоны _Bers Общие вопросы C/C++ 12 01.02.2012 15:51
Массивы, авторизация через ВК, как вытащить данные? Delphinchik PHP 0 23.01.2012 19:12
массивы и строковые данные radiokarazinec Общие вопросы Delphi 13 23.02.2011 05:47
члены последовательности amikulia Помощь студентам 0 14.01.2011 12:35
Массивы,текстовые данные на языке С++ Saferon Помощь студентам 6 13.01.2011 18:00