C++: nowe połączenie, które zachowuje się jak calloc?
Czy Jest jakiś telefon do new
żeby mieć zerową pamięć jak calloc
?
11 answers
Wbrew temu, co niektórzy mówią w swoich odpowiedziach, tojest możliwe.
char * c = new char[N]();
Spowoduje, że zero zainicjalizuje wszystkie znaki (w rzeczywistości nazywa się to inicjalizacją wartości. Ale inicjalizacja wartości będzie zerową inicjalizacją dla wszystkich jej członków tablicy typu scalar). Jeśli o to ci chodzi.
Warto zauważyć, że działa również dla (tablic) typów klas bez deklarowanego przez użytkownika konstruktora, w którym to przypadku każdy z nich jest wartością inicjalizacja:
struct T { int a; };
T *t = new T[1]();
assert(t[0].a == 0);
delete[] t;
To nie jest jakieś rozszerzenie. Działał i zachowywał się podobnie również w C++98. Właśnie tam została nazwana domyślna inicjalizacja zamiast inicjalizacji wartości. Inicjalizacja zerowa jest jednak wykonywana w obu przypadkach dla skalarów lub tablic typu Skalar lub POD.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-30 19:11:04
Nie, ale dość łatwo jest stworzyć nową wersję, która działa jak calloc. Można to zrobić w taki sam sposób, jak zaimplementowana jest wersja No-throw new.
SomeFile.h
struct zeromemory_t{};
extern const zeromemory_t zeromemory;
void* __cdcel operator new(size_t cbSize, const zeromemory_t&);
SomeFile.cpp
const zeromemory_t zeromemory;
void* _cdecl operator new(size_t cbSize, const zeromemory_t&)
{
void *mem = ::operator new(cbSize);
memset(mem,0,cbSize);
return mem;
}
Teraz możesz wykonać następujące czynności, aby uzyskać nowy z zerową pamięcią
MyType* pMyType = new (zeromemory) MyType();
Dodatkowo musisz robić inne zabawne rzeczy, takie jak define new [], które są również dość proste.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-30 20:20:31
Nie. Nawet nie myśl o zrobieniu czegoś takiego:
YourClass *var = new YourClass;
memset(var, 0, sizeof(YourClass));
Możesz skończyć niszcząc swój VTABLE(jeśli twoja klasa ma taki).
Zalecałbym użycie konstruktorów do wyczyszczenia pamięci wewnętrznej (zmiennych) twojej klasy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-30 18:52:10
Nie. Zawsze będzie domyślnie-inicjalizuje przydzielone elementy,co w przypadku prymitywów nic nie robi. Musisz to sprawdzić wywołaniem std::uninitialized_fill_n lub podobnym.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-30 18:44:52
Możesz wykonać globalne przeciążenie operatora new
i zmusić go do przechwycenia nieprzetworzonej pamięci z calloc()
. W ten sposób pamięć zostaje wyczyszczona przed uruchomieniem konstruktorów, więc nie ma żadnych problemów.
Każda klasa, która sama nadpisuje new, nie otrzyma twojego Specjalnego calloc()
opartego na new
, ale ta klasa i tak powinna być inicjalizowana poprawnie.
Nie zapomnij nadpisać zarówno new
i delete
oraz wersji tablicy...
Coś w stylu:
#include <exception> // for std::bad_alloc
#include <new>
#include <stdlib.h> // for calloc() and free()
void* operator new (size_t size)
{
void *p=calloc(size, 1);
if (p==0) // did allocation succeed?
throw std::bad_alloc();
return p;
}
void operator delete (void *p)
{
free(p);
}
void* operator new[] (size_t size)
{
void *p=calloc(size, 1);
if (p==0) // did allocation succeed?
throw std::bad_alloc();
return p;
}
void operator delete[] (void *p)
{
free(p);
}
Uwaga że te proste wersje nie są dokładnie takie, jakie powinny być - operator new
powinien działać w pętli wywołując new_handler
(jeśli jest zainstalowany) i rzucając wyjątek bad_alloc
tylko wtedy, gdy nie ma new_handler
. Albo coś w tym stylu, będę musiał to sprawdzić i zaktualizować później.
no_throw
.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-30 19:04:04
Używam makra:
#define newclear(TYPE) new(calloc(sizeof(TYPE), 1)) TYPE();
Aby go użyć:
Whatever* myWhatever = newclear(Whatever);
(używa się tu "umieszczania nowego", jak niektóre inne rozwiązania tutaj)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-13 18:53:53
Nie.Musisz ręcznie wyzerować pamięć. Pamiętaj, new
nie chodzi tylko o przydzielanie pamięci, ale także o inicjowanie za pomocą konstruktorów. To jest miejsce, gdzie calloc
jest przydatne w C (który nie ma funkcji inicjalizatora). Możesz napisać wrapper nad new
lub nawet użyć calloc
, ale większość czasu dla obiektów spoza POD nie ma to większego sensu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-30 18:46:06
Jeśli nie nalegasz na użycie new
, możesz po prostu użyć vector: vector<char> buffer; buffer.resize(newsize);
, a zawartość zostanie zerowana.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-30 18:50:08
class MyClass {
public:
void* operator new(size_t bytes) {
return calloc(bytes, 1);
}
}
I możesz zastąpić globalny nowy operator, jeśli chcesz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-30 18:52:01
Możesz powiedzieć:
vector <char> v( 100, 0 );
, który tworzy ciągłą tablicę 100 znaków używając new i inicjalizuje je wszystkie do zera. Następnie można uzyskać dostęp do tablicy za pomocą operatora wektora [] lub wykonując:
char * p = &v[0];
p[3] = 42;
Uwaga uwalnia to również od konieczności wywoływania delete w celu uwolnienia przydzielonej pamięci.
Tak.
int* p_scalar = new int(5);//Does not create 5 elements, but initializes to 5
Dla tablic można użyć czegoś takiego jak memset. Dla systemu windows użyj ZeroMemory lub SecureZeroMemory.
Edit: proszę zobaczyć post @ litb, pokazuje on, jak można zainicjować do 0 dla tablic za pomocą inicjalizacji Nie bezpośredniej, jak powyżej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-30 19:18:47