Hat irgendjemand hier jemals die "Platzierung neu" von C++ verwendet? Wenn ja, wofür? Für mich sieht es so aus, als ob es nur auf memory-mapped Hardware nützlich wäre.
Antworten
Zu viele Anzeigen?Siehe die Datei fp.h im xll-Projekt unter http://xll.codeplex.com Es löst das Problem der "ungerechtfertigten Anbiederung an den Compiler" für Arrays, die ihre Dimensionen gerne mit sich herumtragen.
typedef struct _FP
{
unsigned short int rows;
unsigned short int columns;
double array[1]; /* Actually, array[rows][columns] */
} FP;
Hier ist die Killer-Anwendung für den C++ In-Place-Konstruktor: Ausrichten auf eine Cache-Zeile, sowie andere Potenzen von 2 Grenzen. Hier ist meinen ultraschnellen Algorithmus zur Ausrichtung von Zeigern auf beliebige Potenzen von 2 Grenzen mit 5 oder weniger Einzelzyklusanweisungen :
/* Quickly aligns the given pointer to a power of two boundary IN BYTES.
@return An aligned pointer of typename T.
@brief Algorithm is a 2's compliment trick that works by masking off
the desired number in 2's compliment and adding them to the
pointer.
@param pointer The pointer to align.
@param boundary_byte_count The boundary byte count that must be an even
power of 2.
@warning Function does not check if the boundary is a power of 2! */
template <typename T = char>
inline T* AlignUp(void* pointer, uintptr_t boundary_byte_count) {
uintptr_t value = reinterpret_cast<uintptr_t>(pointer);
value += (((~value) + 1) & (boundary_byte_count - 1));
return reinterpret_cast<T*>(value);
}
struct Foo { Foo () {} };
char buffer[sizeof (Foo) + 64];
Foo* foo = new (AlignUp<Foo> (buffer, 64)) Foo ();
Zaubert das nicht ein Lächeln auf Ihr Gesicht (:-). I C++1x
Ich habe auch eine Idee. C++ hat Null-Grenzkosten-Prinzip . Ausnahmen folgen jedoch nicht diesem Prinzip, so dass sie manchmal mit einem Compilerschalter ausgeschaltet werden.
Schauen wir uns dieses Beispiel an:
#include <new>
#include <cstdio>
#include <cstdlib>
int main() {
struct A {
A() {
printf("A()\n");
}
~A() {
printf("~A()\n");
}
char data[1000000000000000000] = {}; // some very big number
};
try {
A *result = new A();
printf("new passed: %p\n", result);
delete result;
} catch (std::bad_alloc) {
printf("new failed\n");
}
}
Wir weisen hier eine große Struktur zu und prüfen, ob die Zuweisung erfolgreich war, und löschen sie.
Aber wenn wir Ausnahmen ausgeschaltet haben, können wir nicht verwenden, Try-Block, und nicht in der Lage, new[] Fehler zu behandeln.
Wie können wir das also tun? Hier ist wie:
#include <new>
#include <cstdio>
#include <cstdlib>
int main() {
struct A {
A() {
printf("A()\n");
}
~A() {
printf("~A()\n");
}
char data[1000000000000000000] = {}; // some very big number
};
void *buf = malloc(sizeof(A));
if (buf != nullptr) {
A *result = new(buf) A();
printf("new passed: %p\n", result);
result->~A();
free(result);
} else {
printf("new failed\n");
}
}
- Einfaches malloc verwenden
- Prüfen Sie, ob sie auf C-Art fehlgeschlagen ist
- Wenn es erfolgreich ist, verwenden wir die Platzierung neuer
- Manueller Aufruf des Destruktors (wir können nicht einfach delete aufrufen)
- free aufrufen, da wir malloc aufgerufen haben
UPD @Useless schrieb einen Kommentar, der mir die Existenz von neu(nothrow) die in diesem Fall verwendet werden sollte, aber nicht die Methode, die ich zuvor geschrieben habe. Bitte verwenden Sie nicht den Code, den ich zuvor geschrieben habe. Entschuldigung.
Ich habe noch eine Idee (sie gilt für C++11).
Betrachten wir das folgende Beispiel:
#include <cstddef>
#include <cstdio>
int main() {
struct alignas(0x1000) A {
char data[0x1000];
};
printf("max_align_t: %zu\n", alignof(max_align_t));
A a;
printf("a: %p\n", &a);
A *ptr = new A;
printf("ptr: %p\n", ptr);
delete ptr;
}
Mit dem C++11-Standard gibt GCC das Folgende aus Ausgabe :
max_align_t: 16
a: 0x7ffd45e6f000
ptr: 0x1fe3ec0
ptr
nicht richtig ausgerichtet ist.
Mit C++17 Standard und weiter, GCC gibt die folgende Ausgabe :
max_align_t: 16
a: 0x7ffc924f6000
ptr: 0x9f6000
ptr
richtig ausgerichtet ist.
Wie ich weiß, unterstützte der C++-Standard vor der Einführung von C++17 keine übermäßig ausgerichteten neuen Strukturen, und wenn Ihre Struktur eine Ausrichtung hat, die größer als max_align_t
können Sie Probleme bekommen. Um dieses Problem in C++11 zu umgehen, können Sie Folgendes verwenden aligned_alloc
.
#include <cstddef>
#include <cstdlib>
#include <cstdio>
#include <new>
int main() {
struct alignas(0x1000) A {
char data[0x1000];
};
printf("max_align_t: %zu\n", alignof(max_align_t));
A a;
printf("a: %p\n", &a);
void *buf = aligned_alloc(alignof(A), sizeof(A));
if (buf == nullptr) {
printf("aligned_alloc() failed\n");
exit(1);
}
A *ptr = new(buf) A();
printf("ptr: %p\n", ptr);
ptr->~A();
free(ptr);
}
ptr
es ausgerichtet in diesem Fall.
max_align_t: 16
a: 0x7ffe56b57000
ptr: 0x2416000
- See previous answers
- Weitere Antworten anzeigen