2010-01-20 2 views
6

Пожалуйста, обратите внимание на следующее:C STL ++ контейнер и место строительства

class CMyClass 
{ 
public: 
    CMyClass() 
    { 
    printf("Constructor\n"); 
    } 
    CMyClass(const CMyClass&) 
    { 
    printf("Copy constructor\n"); 
    } 
}; 

int main() 
{ 
    std::list<CMyClass> listMyClass; 

    listMyClass.resize(1); 

    return 0; 
} 

Он производит следующий вывод:

Конструктор

конструктор копирования

Теперь мой вопрос: как избежать конструктора копирования? Или по-другому: как я могу создавать объекты внутри контейнера STL без ненужной операции копирования. Есть ли способ сделать «на месте» с использованием конструктора по умолчанию?


Обновление - ответы до сих пор:

  1. Это не может быть сделано
  2. Используйте указатели или умные указатели вместо.

Умные указатели являются излишним для моего применения. Но я действительно удивляюсь, почему этого не может быть сделано. Похоже, это такая очевидная вещь, которую нужно делать. Любые другие идеи? Я даже принять неприятный хак, если он работает ...


Решение

Я думаю, что я только что нашел решение моей проблемы со всеми комментариями и ответами, заданные здесь. Решение состоит в том, чтобы создать пустой объект и сохранить его с единственной целью использовать его позже для создания чистых копий. Затем вы можете использовать один из методов, которые принимают ссылку (например, push_back или insert). Это по-прежнему вызывает конструктор копирования для каждого нового объекта вставленного, но, по крайней мере, это не как конструктор по умолчанию и конструктор копирования:

int main() 
{ 
    CMyClass Empty; 

    std::list<CMyClass> listMyClass; 

    for (int c=0; c<10; ++c) 
    { 
    listMyClass.push_back(Empty); 
    } 

    return 0; 
} 
+0

Это может показаться очевидная вещь, но с функциональной точки зрения это не имеет значения, и несколько алгоритмов (sort, remove, ...) также используют копирование, поэтому будьте готовы к копированию;) (См. также http: //www.devx .com/tips/Tip/13606) – stefaanv

+0

Очевидная вещь? Почему это? Почему копирование проблемы? – jalf

+0

Очевидно? Если вы вызвали 'mylist.resize (10)', как бы вы ожидали, что закончите с десятью различными объектами, если они не являются копиями? – visitor

ответ

8

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

1

использование указателей

std::list<CMyClass*> listMyClass; 
+2

еще лучше: используйте интеллектуальный указатель, автоматически создавая/уничтожая рассматриваемый объект – user231967

+2

Только не auto_ptr. Это приведет к возникновению плохих вещей. –

1

К сожалению, в настоящее время не с станд :: список и аналогичные контейнеры. (Но вы можете написать свой собственный слегка другой контейнер, если вам действительно нужно, и по-прежнему следить за оставшуюся часть интерфейса STL.)

Вы не должны использовать CTOR по умолчанию, однако:

std::list<CMyClass> listMyClass; 
listMyClass.resize(1, obj_to_copy_from); 

Такие, как:

std::list<CMyClass> listMyClass; 
listMyClass.resize(1, CMyClass(use, specific, ctor)); 

Изменить размер выглядит следующим образом:

void list<T>::resize(size_type new_size, T copy_from = T()); 

который создает новый объект (и петь по умолчанию ctor) по умолчанию.

0

использовать указатель или смарт-указатель (повышение :: shared_ptr и не auto_ptr)

1

Было бы полезно, если вектор инициализации позволил новые элементы с конструктором по умолчанию на изменение размера из-за работы, но это не поддерживается. Если вам это действительно нужно, реализуйте пользовательский контейнер - другого выхода нет.

0

вы можете сделать в c11, для более старых версий, vesry просто можно улучшить

вектор

myclas: public vector<A> 
{ 
    push_back(Aconstructor_parameters) 
    { 
     new(_Mylast++) A(Aconstructor_parameters); 
    } 
}; 

при использовании убедитесь, что вы использовали reserve() выделить память

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