Я сделал следующую маленькую программу: (в основном класс, который проверяет, создается ли он, копируется или уничтожается, и основной, который делает некоторые из них)
class Foo
{
public:
Foo(string name): _name(name)
{
cout << "Instance " << _name << " of Foo created!" << std::endl;
};
Foo(const Foo& other): _name(other._name)
{
cout << "Instance " << _name << " of Foo copied!" << std::endl;
};
~Foo()
{
cout << "Instance " << _name << " of Foo destroyed!" << std::endl;
}
string _name;
};
int main( int argc, char**argv)
{
Foo albert("Albert");
Foo bert("Bert");
{
vector<Foo> v1, v2;
system("PAUSE");
v1.push_back(albert);
system("PAUSE");
v2.push_back(bert);
system("PAUSE");
v1 = v2;
system("PAUSE");
}
system("PAUSE");
}
Вывод выглядит следующим образом:
Instance Albert of class Foo created!
Instance Bert of class Foo created!
Press any key...
Instance Albert of class Foo copied!
Instance Albert of class Foo copied! // why another copy?
Instance Albert of class Foo destroyed! // and destruction?
Press any key...
Instance Bert of class Foo copied!
Instance Bert of class Foo copied!
Instance Bert of class Foo destroyed!
Press any key... // v1=v2 why did the albert instance not get destroyed?
Press any key...
Instance Bert of class A destroyed!
Instance Bert of class A destroyed!
Press any key... // there's still an albert living in the void
Мне это кажется очень странным. Зачем мне вообще передавать что-то в качестве ссылки, если оно все равно скопировано дважды? Почему v1.operator=(other) не уничтожает содержащиеся в нем элементы? Это хорошо сочетается с поведением shared_ptr. Может кто-нибудь сказать мне, почему?
ДОПОЛНЕНИЕ Я поставил это в бесконечный цикл и проверил использование памяти, по крайней мере, похоже, что это не приводит к утечке памяти.
ДОПОЛНЕНИЕ Хорошо, мем не проблема, потому что он использует оператор = вместо копирования ctor, хорошо, спасибо. Когда я добавляю
v1.reserve(10);
v2.reserve(10);
имеет место логическое количество копий. без этого он перераспределяет и копирует весь вектор для каждого push_back (что я считаю довольно замедленным даже для небольших векторов). Глядя на это, я подумаю об использовании .reserve и оптимизирую свои операторы присваивания, черт возьми :)
ДОПОЛНЕНИЕ: ОБЗОР
- Все эти проблемы кажутся характерными для VC++2005.
- Если размеры двух контейнеров совпадают, моя реализация использует оператор = для элементов вместо уничтожения старых и копирования новых, что кажется разумной практикой. ЕСЛИ размеры различаются, используется обычное уничтожение и копирование.
- С реализацией 2005 года приходится использовать резерв! В противном случае ужасная и не соответствующая стандарту производительность.
- Эти черные ящики намного чернее, чем я думал.