как @ john-saunders упомянул в своем ответе:
StringWriter всегда будет использовать UTF-16
, поэтому я использовал MemoryStream для этих целей.
В моем случае я использовал кодировку windows-1251.
var xmlSstring = "";
using (var ms = new MemoryStream())
{
var encoding = Encoding.GetEncoding(1251);
var settings = new XmlWriterSettings
{
Indent = true,
Encoding = encoding
};
using (var xmlTextWriter = XmlWriter.Create(ms, settings))
{
doc.Save(xmlTextWriter);
xmlString = encoding.GetString(ms.ToArray());
}
}
I suspect your questions are about std::vector< T > (as opposed to an array T[]).
Не используйте new
для создания векторов. Просто положите их в стек.
Деструктор вектора автоматически вызывает деструктор каждого элемента в векторе. Так что вам не нужно беспокоиться об удалении объектов самостоятельно. Однако, если у вас есть вектор указателей, объекты, на которые ссылаются указатели, не будут очищены , а не . Вот пример кода. Для ясности я опускаю большинство деталей:
class HeapInt
{
public:
HeapInt(int i) {ptr = new int(i);}
~HeapInt() {delete ptr;}
int& get() {return *ptr;}
private:
int* ptr;
};
int main()
{
// this code DOES NOT leak memory
std::vector<HeapInt> vec;
for (int i = 0; i < 10; ++i)
{
HeapInt h(i);
vec.push_back(h);
}
return 0;
}
Даже если main () выдает исключение, память не теряется. Однако этот код вызывает утечку памяти :
int main()
{
// this code though, DOES leak memory
std::vector<int*> vec;
for (int i = 0; i < 10; ++i)
{
int* ptr = new int(i);
vec.push_back(ptr);
}
// memory leak: we manually invoked new but did not manually invoke delete
return 0;
}
Да, вы можете доверять векторам, которые убирают за собой.
ОДНАКО Нельзя доверять, что вектор материала очищает за собой. Что нужно очистить, может быть что-то, что сохраняется вне вашего приложения. Если это память, это не беспокойство. Если он следит за тем, чтобы все теги XML были закрыты, тогда ОС не сможет вам помочь.
Например, что, если у вас есть вектор некоторого шаткого объекта блокировки вроде этого:
class CLock
{
public:
CLock() {}
~CLock() {}
void Lock(...) {...}
void Unlock(...) {...}
};
std::vector<CLock> myLockVec;
Как бы ваш вектор CLock знает, как разблокировать все, когда это будет сделано? Векторы не созданы, чтобы знать о блокировках.
По сути, это та же ситуация, что и с вектором указателей:
std::vector<int*> myIntVec;
Как вектор узнает, какие указатели здесь были удалены и имеют NULL, а какие на самом деле есть? Возможно, некоторые из них были удалены и установлены на ваше специальное значение 0xdeadbeef, то есть удалено.
Дело в том, что вектор не имеет возможности знать это или знать, что его элементы являются указателями, блокировками или чем-то еще. Они просто должны быть объектами, у которых есть конструкторы по умолчанию и которые можно копировать, а также соответствовать другим требованиям, предъявляемым вектором к своим элементам.
Решение состоит в том, чтобы убедиться, что любой вектор HOLDS должен отвечать за его очистку. Это называется RAII - выделение ресурсов - это инициализация, что более важно в данном случае, уничтожение ресурсов - это освобождение. В нашем примере с CLock, приведенном выше, ответ очевиден, не забудьте разблокировать, когда мы закончим!
class CLock
{
...
~Clock()
{
if (locked)
{
Unlock();
}
}
}
Но с указателями это не так очевидно. Решение - заключить указатель в класс smart_ptr.
Я полагаю, что вы говорите о std :: vector, а не о языковых массивах.
Любая память, созданная вашей программой, будет освобождена при выходе. Это особенность операционной системы, не имеющая ничего общего с языком программирования, который вы используете.
«Каждый раз, когда я запускаю свою программу, я теряю оперативную память», должно быть, из-за какого-то другого эффекта - как вы это измеряете?
] Относительно того, почему вы использовали "новый" - две причины:
Один из нас двоих здесь немного запутался.
Если вы используете std :: vector, вам не нужно вручную выделять память для его элементов. Дополнительное пространство будет автоматически выделяться при необходимости, когда вы выполняете push_back (). Если вам по какой-то причине нужно предварительно выделить все пространство, вы можете вызвать функцию reserve (). В любом случае, при уничтожении вектора память автоматически освобождается для вас.
Если вы выполняете new std :: vector, вы получаете указатель на вектор. Это ничем не отличается от вызова new для любого другого класса. Вы создаете указатель на объект этого класса, и он будет уничтожен при вызове delete. Если вам не нравится такое поведение, попробуйте создать свой вектор в стеке.
Что касается «потерянной памяти», что говорит @RichieHindie.
По второму вопросу:
могут ли векторы, созданные без ключевого слова NEW, действительно быть оставлены на их усмотрение собственные устройства и доверились разобраться с собой, даже если код прерывается в середине потока
В то время как нормальное завершение программы (включая завершение по исключению) гарантирует выполнение деструкторов (с некоторыми придирками относительно статических данных - теоретически они тоже должны выполняться, на практике вы можете иногда получить проблемы), жесткий сбой процесса не может гарантировать какое-либо поведение - например, kill -9
гарантированно завершит вашу программу как можно скорее, не давая ей возможности выполнить какие-либо деструкторы или что-то еще .
Another scenario not mentioned in regards to when you'd want to use "new", is in some cases when a vector is a member variable of a class. The NULL can be used as an additional semaphore, for example during create on demand; also, if the vector usage is sparsely populated on your class, then not even creating one unless it's really needed will save you memory, at the expense of the extra 4 byte penalty on all instances as well as the runtime penalty of the pointer indirection.