LINUX.ORG.RU

C++ - вопрос


0

0

Простейшая, в общем, программа...

#include <iostream>
#include <algorithm>
#include <iterator>

class C
{
   private:
      int i;
   public:
      C():i(0){}
      C(int i_):i(i_){}
      friend std::ostream& operator<<(std::ostream&,const C&);
};

std::ostream& operator<<(std::ostream& ostr,const C& c)
{
   return ostr << c.i;
}

int main()
{ 
   {
      C* mas = new C[10](-1);
      std::copy(mas,mas+10,std::ostream_iterator<C>(std::cout," "));
      std::cout << std::endl;
      delete [] mas;
   }
   {
      int* mas = new int[10](1);
      std::copy(mas,mas+10,std::ostream_iterator<int>(std::cout," "));
      std::cout << std::endl;
      delete [] mas;
   }
   return 0;
}

А вот результат ее работы:
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 
0 -1 -1 -1 -1 -1 -1 -1 -1 -1 

Почему так получилось - в общем, понятно. Вопросы:
1) это во всех компиляторах С++ так, или только в gnu c++?
2) Что говорит по этому поводу стандарт? Это - нормально или нет?


anonymous

>Почему так получилось - в общем, понятно. Вопросы:
>1) это во всех компиляторах С++ так, или только в gnu c++?
>2) Что говорит по этому поводу стандарт? Это - нормально или нет?

g++-3.4 -o tmp ./tmp.cc && ./tmp
./tmp.cc: In function `int main()':
./tmp.cc:23: error: ISO C++ forbids initialization in array new
./tmp.cc:29: error: ISO C++ forbids initialization in array new

anonymous
()
Ответ на: комментарий от anonymous

Нда... Т.е. чем решать проблему - проще ее запретить! Получается, что теперь если у класса дефолтный конструктор запрещен, то массив объектов я уже не создам... Прикольно...

anonymous
()
Ответ на: комментарий от anonymous

создашь, именно для это в стандартной библиотеке есть контейнер vector

fghj ★★★★★
()
Ответ на: комментарий от anonymous

In C++, the operator new allocates memory for an object and then creates an object at that location by calling a constructor. Occasionally, however, it is useful to separate those two operations. [1] If i is an iterator that points to a region of uninitialized memory, then you can use construct to create an object in the location pointed to by i. Raw_storage_iterator is an adaptor that makes this procedure more convenient. If r is a raw_storage_iterator, then it has some underlying iterator i. The expression *r = x is equivalent to construct(&*i, x).
Example

class Int {
public:
  Int(int x) : val(x) {}
  int get() { return val; }
private:
  int val;
};    

int main()
{
  int A1[] = {1, 2, 3, 4, 5, 6, 7};
  const int N = sizeof(A1) / sizeof(int);

  Int* A2 = (Int*) malloc(N * sizeof(Int));     
  transform(A1, A1 + N, 
            raw_storage_iterator<Int*, int>(A2),
            negate<int>());
}

Definition
Defined in the standard header memory, and in the nonstandard backward-compatibility header iterator.h.

anonymous
()
Ответ на: комментарий от anonymous

Да, с raw_storage_iterator - интересный момент. Однако, это только часть
решения. Иначе говоря, я каким-то образом сначала должен выделить 
память, затем должен сделать что-то типа

std::fill_n(std::raw_storage_iterator<C*,int>(buf),10,1);

Да, сейчас проверил - действительно работает... 
Тогда, вдогонку еще вопрос: 
- если память выделялась через malloc, то как мне ее корректно освободить - если для этого требуется вызов деструктора...

anonymous
()
Ответ на: комментарий от anonymous

from SGI Standard Template Library Programmer's Guide:

Prototype
Destroy is an overloaded name; there are actually two destroy functions.

template <class T> void destroy(T* pointer);

template <class ForwardIterator>
void destroy(ForwardIterator first, ForwardIterator last);

Description
In C++, the operator delete destroys an object by calling its destructor, and then deallocates the memory where that object was stored. Occasionally, however, it is useful to separate those two operations. [1] Destroy calls an object's destructor without deallocating the memory where the object was stored.

The first version of destroy destroys the object pointed to by pointer by calling the destructor T::~T(). The memory pointed to by pointer is not deallocated, and can be reused for some other object.

The second version of destroy destroys all of the objects in the range of elements [first, last). It is equivalent to calling destroy(&*i) for each iterator i in the range [first, last).

Example


int main()
{
  Int A[] = { Int(1), Int(2), Int(3), Int(4) };

  destroy(A, A + 4);
  construct(A,     Int(10));
  construct(A + 1, Int(11));
  construct(A + 2, Int(12));
  construct(A + 3,  Int(13));
}

Notes

[1] In particular, destroy, along with other low-level memory allocation primitives, is used to implement container classes.

See also
Allocators, construct, uninitialized_copy, uninitialized_fill, uninitialized_fill_n

anonymous
()
Ответ на: комментарий от anonymous

Итого: - STL все больше срастается с компилятором. Если в проекте по каким-то причинам нельзя ее использовать - возможна задница.

anonymous
()
Ответ на: комментарий от anonymous

> Если в проекте по каким-то причинам нельзя ее использовать - возможна задница.

все что можно сделать STL можно сделать и вручную.. Деструктор можно вызывать явно: p->~C();

dilmah ★★★★★
()
Ответ на: комментарий от anonymous

Все эти возможности были 10 лет назад, еще до принятия стандарта. Скорее качество реализации стандарта в g++ сейчас значительно улучшилось

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.