C ++: эффективный swap () при использовании пользовательского распределителя - PullRequest
14 голосов
/ 05 сентября 2011

Мне кажется, это месяц шаблонов C ++ ...

У меня есть SecureString.SecureString выглядит так же, как std :: string, за исключением того, что он использует собственный распределитель, который обнуляет при уничтожении:

class SecureString
{
public:
  typedef std::basic_string< char, std::char_traits<char>, zallocator<char> > SecureStringBase;
  typedef zallocator<char>::size_type size_type;
  static const size_type npos = static_cast<size_type>(-1);
  ....
private:
  SecureStringBase m_base;
};

Полный код для SecureString можно найти по адресу http://code.google.com/p/owasp-esapi-cplusplus/source/browse/trunk/esapi/util/SecureString.h; и кодРаспределитель можно найти по адресу http://code.google.com/p/owasp-esapi-cplusplus/source/browse/trunk/esapi/util/zAllocator.h.

. В настоящее время мы определили swap, который принимает std :: string в качестве аргумента:

void SecureString::swap(std::string& str)
{
  SecureStringBase temp(str.data(), str.size());
  m_base.swap(temp);
  str = std::string(temp.data(), temp.size());
}

Я чувствую, что мне не хватаетвозможность в swap, потому что базовые типы отличаются только распределителями.Кто-нибудь может увидеть способ избежать временного?Можно ли использовать rebind, чтобы ускорить этот запуск?

РЕДАКТИРОВАТЬ: SecureString::swap(std::string& str) теперь нет.Ссылка на функцию в этой теме оставлена ​​для потомков.

Джефф

1 Ответ

9 голосов
/ 05 сентября 2011

К сожалению ... нет.

Это не то, для чего rebind. rebind используется потому, что распределитель предназначен для выделения объектов одного типа и только одного типа (std::allocator<T>) в STL.

Однако есть хитрость. Например, когда вы создаете экземпляр std::list<T, std::allocator<T>>, allocator не должен выделять T s, ему нужно вместо этого выделять некоторую внутреннюю структуру, такую ​​как __list_node<T>, и именно тогда rebind используется, он создает новый распределитель, родственный элемент прецедента (они отличаются только параметром шаблона и, вероятно, совместно используют один и тот же пул памяти под крышками).

В вашем случае, однако, ваш распределитель и распределитель std::string отличаются, и поэтому они не могут обмениваться памятью. Таким образом, у вас есть , чтобы сделать копию.

Вы можете оптимизировать операцию void swap(SecureString&, SecureString&), но не эту.

Один вопрос: почему бы не typedef std::string<char, SecureAllocator<char>> SecureString;?

...