С join()
и zip()
.
>>> ''.join(''.join(item) for item in zip(u,l))
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
В зависимости от Вашего использования существует несколько опций, с которыми Вы могли пойти сюда:
Делают копию каждым разом, когда Вы создаете животное:
class AnimalLister
{
public:
Animal getNewAnimal()
{
return Animal();
}
};
int main() {
AnimalLister al;
Animal a1 = al.getNewAnimal();
Animal a2 = al.getNewAnimal();
}
Профессионалы:
Недостатки:
Animal
иметь конструктора копии хорошего поведения. Animal
larg и комплекс, хотя оптимизация возвращаемого значения может облегчить это во многих ситуациях. Animal
, как они будут , резал вниз к плоскости Animal
, теряя все дополнительные данные в подклассе. Возврат shared_ptr<Animal>
:
class AnimalLister
{
public:
shared_ptr<Animal> getNewAnimal()
{
return new Animal();
}
};
int main() {
AnimalLister al;
shared_ptr<Animal> a1 = al.getNewAnimal();
shared_ptr<Animal> a2 = al.getNewAnimal();
}
Профессионалы:
Animal
для определения конструктора копии. Недостатки:
Дорожка весь Animal
выделения в [1 110]
class AnimalLister
{
vector<Animal *> Animals;
public:
Animal *getNewAnimal()
{
Animals.push_back(NULL);
Animals.back() = new Animal();
return Animals.back();
}
~AnimalLister()
{
for(vector<Animal *>::iterator iAnimal = Animals.begin(); iAnimal != Animals.end(); ++iAnimal)
delete *iAnimal;
}
};
int main() {
AnimalLister al;
Animal *a1 = al.getNewAnimal();
Animal *a2 = al.getNewAnimal();
} // All the animals get deleted when al goes out of scope.
Профессионалы:
Animal
с на сингле delete
. Недостатки:
Я советую возвращаться std::tr1::shared_ptr
(или boost::shared_ptr
, если Ваша реализация C++ не имеет TR1) вместо необработанного указателя. Так, вместо того, чтобы использовать Animal*
, используйте std::tr1::shared_ptr<Animal>
вместо этого.
Общие указатели обрабатывают ссылочное отслеживание для Вас и удаляют объект автоматически, при отсутствии ссылок, оставленных ему.
simpliest путь состоит в том, чтобы возвратить интеллектуальный указатель вместо регулярных указателей. Например:
std::auto_ptr< Animal> getNewAnimal()
{
std::auto_ptr< Animal > animal1( new Animal() );
return animal1;
}
, Если Вы в состоянии использовать TR1 или Повышение, можно также использовать shared_ptr<>.
Своего рода классическая проблема с указателями и выделенной памятью. Это об ответственности - кто ответственен за чистку памяти, выделенной объектом AnimalLister.
Вы могли сохранить от указателя на каждое из тех выделенных Животных в самом AnimalLister и иметь его, очищают вещи.
, Но, у Вас действительно есть несколько указателей на Животных, сидящих там в основном (), который сослался бы на память, которая была удалена.
Одна из причин я думаю, что решения для подсчета ссылок работают лучше, чем прокрутка Вашего собственного решения.
реализуют 'freeAnimal (Животное*)' метод, который делает его очевидным, что удаление указателя животных требуется.
альтернативный путь состоит в том, чтобы просто возвратить объект животных непосредственно, никакие указатели, никакие вызовы к новому. Конструктор копии удостоверится, что вызывающая сторона добирается, их собственное животное возражают, что они могут сохранить на "куче" или стеке, или копировать в контейнер, как они требуют.
Так:
class AnimalLister
{
Animal getAnimal() { Animal a; return a; }; // uses fast Return Value Optimisation
};
Animal myownanimal = AnimalLister.getAnimal(); // copy ctors into your Animal object
RVO означает, что возврат объекта вместо указателя на самом деле быстрее (поскольку компилятор не создает новый объект и копирует его в объект вызывающей стороны, но использует объект вызывающей стороны непосредственно).
Или Вы могли следовать за подходом COM-выхода и применить простой подсчет ссылок.
, Если подсчет ссылок совершает нападки 0, объект удаляет себя.
в конечном счете, что shared_ptr делает под капотом, но это дает Вам больше контроля тем, что продолжается, и по моему опыту легче отладить. (Его также очень межплатформенный).
я не дал shared_ ptr слишком много шанса в моей разработке пока еще, так, чтобы мог служить Вашим целям отлично.
Время для освобождения памяти, занятой объектом, - когда Вам больше не нужен тот конкретный объект. В Вашем особом случае пользователе класса AnimalLister запросил указатель на новый выделенный объект класса Животное. Так, он - тот, который ответственен за освобождение памяти, когда ему действительно больше нужен тот указатель/объект.
AnimalLister lister;
Animal* a = lister.getNewAnimal();
a->sayMeow();
delete a;
, По-моему, нет никакой потребности сверхспроектировать что-либо в этом случае. AnimalLister является просто фабрикой, которая создает новые объекты Животных и вот именно.
Мне действительно нравится ответ Josh's, но я думал, что мог бы добавить другой шаблон, потому что он еще не был перечислен. Идея является просто силой клиентский код для контакта с отслеживанием животных.
class Animal
{
...
private:
//only let the lister create or delete animals.
Animal() { ... }
~Animal() { ... }
friend class AnimalLister;
...
}
class AnimalLister
{
static s_count = 0;
public:
~AnimalLister() { ASSERT(s_count == 0); } //warn if all animals didn't get cleaned up
Animal* NewAnimal()
{
++count;
return new Animal();
}
void FreeAnimal(Animal* a)
{
delete a;
--s_count;
}
}
В подробном обсуждении Скоттом Мейерсом он приходит к выводу, что лучше всего использовать shared_ptr или auto_ptr.