Можно решить проблему без копирования всех std::strings
, пока функция не изменяет переданную в char**
. В противном случае я не вижу альтернативы, кроме как скопировать все в новую структуру char ** ` (см. Второй пример) .
void old_func(char** carray, size_t size)
{
for(size_t i = 0; i < size; ++i)
std::cout << carray[i] << '\n';
}
int main()
{
std::vector<std::string> strings {"one", "two", "three"};
std::vector<char*> cstrings;
cstrings.reserve(strings.size());
for(size_t i = 0; i < strings.size(); ++i)
cstrings.push_back(const_cast<char*>(strings[i].c_str()));
// Do not change any of the strings here as that will
// invalidate the new data structure that relies on
// the returned values from `c_str()`
//
// This is not an issue after C++11 as long as you don't
// increase the length of a string (as that may cause reallocation)
if(!cstrings.empty())
old_func(&cstrings[0], cstrings.size());
}
ПРИМЕР 2: Если функция должна изменить переданные в данных:
void old_func(char** carray, size_t size)
{
for(size_t i = 0; i < size; ++i)
std::cout << carray[i] << '\n';
}
int main()
{
{
// pre C++11
std::vector<std::string> strings {"one", "two", "three"};
// guarantee contiguous, null terminated strings
std::vector<std::vector<char>> vstrings;
// pointers to rhose strings
std::vector<char*> cstrings;
vstrings.reserve(strings.size());
cstrings.reserve(strings.size());
for(size_t i = 0; i < strings.size(); ++i)
{
vstrings.emplace_back(strings[i].begin(), strings[i].end());
vstrings.back().push_back('\0');
cstrings.push_back(vstrings.back().data());
}
old_func(cstrings.data(), cstrings.size());
}
{
// post C++11
std::vector<std::string> strings {"one", "two", "three"};
std::vector<char*> cstrings;
cstrings.reserve(strings.size());
for(auto& s: strings)
cstrings.push_back(&s[0]);
old_func(cstrings.data(), cstrings.size());
}
}
ПРИМЕЧАНИЕ: пересмотрен для обеспечения лучшего кода.
Вместо статического класса вы должны использовать обычный класс с одноэлементным шаблоном (то есть вы сохраняете один единственный экземпляр класса, на который, возможно, ссылается одно статическое свойство в самом классе) . Затем у вас может быть деструктор или, что еще лучше, комбинация деструктора и метода Dispose .
Например, если теперь у вас есть:
static class MyClass
{
public static void MyMethod() {...}
}
//Using the class:
MyClass.MyMethod();
, вместо этого вы получите:
class MyClass : IDisposable
{
public static MyClass()
{
Instance=new MyClass();
}
public static MyClass Instance {get; private set;}
public void MyMethod() {...}
public void Dispose()
{
//...
}
~MyClass()
{
//Your destructor goes here
}
}
//Using the class:
MyClass.Instance.MyMethod();
(Обратите внимание, как экземпляр создается в статическом конструкторе, который вызывается при первом обращении к любому из статических членов класса)
Статические классы не имеют деструкторов, потому что статический класс никогда не уничтожается.
Если вы хотите создать и уничтожить несколько его экземпляров, он не должен быть статическим. Сделайте его полным классом.
Деструкторы в любом случае использовать для этой цели не следует. Используйте IDisposable / Dispose.
1. Почему? - Тип не может иметь конструктора как такового, как в обычном понимании конструкторов экземпляров. В общем, его иногда называют методом «статического инициализатора», но Microsoft использует терминологию «конструктор типа» (и у него есть особые ограничения) - вы помещаете в него код для инициализации типа / класса - если это был конструктор экземпляра, он мог бы быть перегружен. Это статическое ограничение для «конструктора типов» связано с тем, что .NET CLR отвечает за загрузку шаблона класса в куче и не позволяет указывать параметры в этом случае (потому что как бы вы могли передавать аргументы). Поскольку в самом строгом смысле программист не несет ответственности за вызов конструктора типа, не имеет большого смысла позволять программисту кодировать статический деструктор, когда он находится в домене CLR. В конечном итоге среда CLR удалит шаблон класса из кучи, но время жизни шаблона класса больше, чем у его экземпляров, поэтому вы все равно не захотите делать в нем что-либо ресурсоемкое (например, удерживать соединение с базой данных).
2 . Какой? - Синглтон В любом случае я не хочу делать в нем что-либо ресурсоемкое (например, держать открытым соединение с базой данных).
2. Какой? - Синглтон В любом случае я не хочу делать в нем что-либо ресурсоемкое (например, держать открытым соединение с базой данных).
2. Какой? - Синглтон Если вы столкнулись с ситуацией, когда вам кажется, что вам нужно открыть ресурс в шаблоне класса и затем уничтожить его, вы можете подумать, что программный шаблон Singleton имеет только один экземпляр этого класса и, возможно, также реализует интерфейс System.IDiposable для помощи в очистке в дополнение к деструктору. (Я вижу, что кто-то уже опередил меня по образцу кода IDisposable, поэтому на этом я закончу свое решение.)
Статический класс никогда не уничтожается. Завершается вместе с программой. Вы можете использовать шаблон singleton в качестве реализации вместо использования статического класса