ãã®ããŒãžã¯C++20ã«æ¡çšãããèšèªæ©èœã®å€æŽã解説ããŠããŸãã
ã®ã¡ã®C++èŠæ Œã§ããã«å€æŽãããå Žåãããããé¢é£é ç®ãåç §ããŠãã ããã
æŠèŠ
newåŒã§ã¯ãªãmalloc()çä»ã®æ¹æ³ã§ç¢ºä¿ãããã¡ã¢ãªé åã«ã¯ãæç€ºçã«ãªããžã§ã¯ãã®æ§ç¯ãè¡ããŸã§æ³å®ããåã®ãªããžã§ã¯ãã¯çåæéå
ã«ãªãããã®ã¢ã¯ã»ã¹ïŒèªã¿æžãïŒã¯æªå®çŸ©åäœãåŒãèµ·ããã
struct X {
int a;
int b;
};
X *make_x() {
// malloc()ã¯ã¡ã¢ãªã®ç¢ºä¿ã ããè¡ã
X *p = (X*)malloc(sizeof(struct X));
// pã®é åã«ã¯Xã®ãªããžã§ã¯ããæ§ç¯ãããŠããªã
p->a = 1; // ð UB
p->b = 2; // ð UB
return p;
}
ãã®æ§ãªã³ãŒãã¯çŽç²ãªC++ã§ã¯newåŒãçšããããšã«ãªãããã®å Žåã¯åé¡ãªãã
// newåŒã䜿çšããå Žå
X *make_x() {
// newåŒã¯ã¡ã¢ãªã®ç¢ºä¿ãšãªããžã§ã¯ãæ§ç¯ãè¡ã
X *p = new X;
// pã®é åã«ã¯Xã®ãªããžã§ã¯ããæ§ç¯æž
p->a = 1; // â
ok
p->b = 2; // â
ok
return p;
}
äžçªæåã®malloc()ãçšããã³ãŒãã¯äž»ã«Cã®ã³ãŒããšå
±æããéšåã§çŸããããšããããCã§ã¯åé¡ãªããã®ã®C++ã³ãŒããšããŠã³ã³ãã€ã«ããå Žåã«ã®ã¿æªå®çŸ©åäœãåŒãèµ·ãããC++20ããã¯ããã®æ§ãªã³ãŒãã®C/C++çžäºéçšæ§åäžã®ããã«ãæç€ºçã«ãªããžã§ã¯ããæ§ç¯ããå¿
èŠããªããšã¿ãªãããšã®ã§ããäžéšã®åïŒimplicit-lifetime typesïŒã«éã£ãŠãæªåæåé åãžã®ã¢ã¯ã»ã¹æã«æé»çã«ïŒèªåçã«ïŒãªããžã§ã¯ããæ§ç¯ãããæ§ã«ãªããæªå®çŸ©åäœãåé¿ã§ããæ§ã«ãªãã
åé¡ãšãªãä»ã®äŸ
以äžã®äŸã¯ãã®å€æŽã«ãã£ãŠè§£æ±ºãããäŸã§ãããC++17以åã¯æªå®çŸ©åäœãåŒãèµ·ãããã®ã§ããã
operator new
newåŒã§ã¯ãªãoperator new()ãçŽæ¥äœ¿çšããå Žåã¯åæ§ã®åé¡ãããã
// newæŒç®åã䜿çšããå Žå
X *make_x() {
// operator new()ã¯ã¡ã¢ãªã®ç¢ºä¿ã ããè¡ã
X *p = (X*)::operator new(sizeof(struct X));
// pã®é åã«ã¯Xã®ãªããžã§ã¯ããæ§ç¯ãããŠããªã
p->a = 1; // ð UB
p->b = 2; // ð UB
return p;
}
å ±çšäœã®ã³ããŒ
union U {
int n;
float f;
};
float pun(int n) {
// U::nã®çåæéãéå§
U u = {.n = n};
// ãã®ã³ããŒã§ã¯uã®ãªããžã§ã¯ã衚çŸãã³ããŒããããã®ã®ãã¡ã³ãã®çåæéã¯éå§ãããªã
// ãã®ãããã¢ã¯ãã£ãã¡ã³ããç¡ãç¶æ
ãšãªã
U u2 = u;
// u2.fã¯éã¢ã¯ãã£ã
return u2.f; // ð UB
}
ãã€ãé åã®èªã¿èŸŒã¿
// äœããã€ãåã¹ããªãŒã ãåãåã£ãŠåŠçãã颿°ãšãã
void process(Stream *stream) {
// ãã€ãé
åã®èªã¿åºã
std::unique_ptr<char[]> buffer = stream->read();
// å
é ãã€ãã®ç¶æ
ã«ãã£ãŠåå²
if (buffer[0] == FOO) {
process_foo(reinterpret_cast<Foo*>(buffer.get())); // #1
} else {
process_bar(reinterpret_cast<Bar*>(buffer.get())); // #2
}
}
1ã€ã®é åã«è€æ°ã®åã®ãªããžã§ã¯ããåæã«çåæéå
ã«ããããšã¯ãªããããstream->read()ãå
éšã§Foo, Barã©ã¡ããã®ãªããžã§ã¯ããæ§ç¯ããŠãããšããŠãã#1ãš#2ã®ã©ã¡ããã®ãã¹ã¯æªå®çŸ©åäœãåŒãèµ·ããããããŠããã®æ§ãªã³ãŒãã§ã¯å€ãã®å Žåãæç€ºçã«ãªããžã§ã¯ããæ§ç¯ãããããšã¯ãªãã
åçé åã®å®è£
// std::vectorã®æ§ãªåçé
ååãå®è£
ããã
template<typename T>
struct Vec {
char *buf = nullptr;
char *buf_end_size = nullptr;
char *buf_end_capacity = nullptr;
void reserve(std::size_t n) {
char *newbuf = (char*)::operator new(n * sizeof(T), std::align_val_t(alignof(T)));
std::uninitialized_copy(begin(), end(), (T*)newbuf); // #a ð UB
::operator delete(buf, std::align_val_t(alignof(T)));
buf = newbuf;
buf_end_size = newbuf + sizeof(T) * size(); // #b ð UB
buf_end_capacity = newbuf + sizeof(T) * n; // #c ð UB
}
void push_back(T t) {
if (buf_end_size == buf_end_capacity)
reserve(std::max<std::size_t>(size() * 2, 1));
new (buf_end_size) T(t);
buf_end_size += sizeof(T); // #d ð UB
}
T *begin() { return (T*)buf; }
T *end() { return (T*)buf_end_size; }
std::size_t size() { return end() - begin(); } // #e ð UB
};
int main() {
Vec<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
for (int n : v) { /*...*/ } // #f ð UB
}
C++ã«ãããŠã¯ããã€ã³ã¿ã«å¯ŸããæŒç®ïŒ+ -ãªã©ïŒã¯ãã®ãã€ã³ã¿ãé
åãªããžã§ã¯ããæããŠããå Žåã«ã®ã¿æå¹ãšãªãããäŸäžã®#a #b #c #d #e #fã§äœ¿çšããããã€ã³ã¿ã®æãé åã«ã¯ããããé
åãªããžã§ã¯ããçåæéã«ãªãïŒæ£ç¢ºã«ã¯ãéé
åãªããžã§ã¯ãã®ãã€ã³ã¿ã®å Žåã¯èŠçŽ æ°1ã®é
åãšããŠæ±ããããããã®äŸã®å Žåã¯ãããæºããããšã¯ã»ãŒãªããæºãããªããã®ãšããïŒããã®ããããã®ãã€ã³ã¿ãã€ãã¬ãŒã¿ã®æ§ã«äœ¿çšããããšã¯æªå®çŸ©åäœãåŒãèµ·ããã
仿§
implicit-lifetime types
æç€ºçã«ãªããžã§ã¯ããæ§ç¯ããå¿ èŠããªããšã¿ãªãããšã®ã§ããäžéšã®åã¯implicit-lifetime typesãšåŒã°ããæ¬¡ã®ããããã«è©²åœããåã§ãã
- ã¹ã«ã©å
- é
åå
- èŠçŽ åã¯åããªã
- implicit-lifetime class types
- ãã¹ãã©ã¯ã¿ããŠãŒã¶ãŒå®çŸ©ãããŠããªãéæäœåããããã¯
- å°ãªããšã1ã€ã®è³æ Œã®ããããªãã¢ã«ã³ã³ã¹ãã©ã¯ã¿ãšãããªãã¢ã«ã§åé€ãããŠããªããã¹ãã©ã¯ã¿ãæã€å
- 1~3ã®CV修食ãããå
ãªããžã§ã¯ããæé»çã«æ§ç¯ããæäœ
æšæºã©ã€ãã©ãªäžã®æ¬¡ã®é¢æ°ã¯ãimplicit-lifetime typesã«å¯ŸããŠäœ¿çšããå Žåã«ããã®æ¯ãèãã®äžç°ãšããŠæå®ãããé åå ã«ãã®ãªããžã§ã¯ããæé»çã«æ§ç¯ãã
newæŒç®åoperator newoperator new[]
- ã¢ãã±ãŒã¿
- Cã©ã€ãã©ãªé¢æ°
std::aligned_allocstd::callocstd::mallocstd::reallocstd::memcpystd::memmove
std::bit_cast
ãããã®æäœã¯ãããããæ¬¡ã®ããã«ãªããžã§ã¯ããæé»çã«æ§ç¯ãã
newæŒç®åãšCã®ã¡ã¢ãªç¢ºä¿é¢æ°- è¿ãããé åã«ãªããžã§ã¯ããæ§ç¯ããæ§ç¯ãããé©åãªãªããžã§ã¯ããžã®ãã€ã³ã¿ãè¿ã
calloc/reallocã®å Žåãæé»çãªãªããžã§ã¯ãæ§ç¯ã¯ãŒãåã/ã³ããŒãè¡ãããåã«è¡ããã
- è¿ãããé åã«ãªããžã§ã¯ããæ§ç¯ããæ§ç¯ãããé©åãªãªããžã§ã¯ããžã®ãã€ã³ã¿ãè¿ã
std::allocator::allocate- è¿ãããé ååã®é åã«ãã®é ååã®ãªããžã§ã¯ããæ§ç¯ããããé åèŠçŽ ã¯æ§ç¯ãããªã
std::memcpy/std::memmove- ã³ããŒå é åãžã®æé»çãªãªããžã§ã¯ãæ§ç¯ã¯ãã³ããŒå é åã«ã³ããŒãããåã«è¡ããã
std::bit_cast- ãã¹ããããã®ãå«ããŠãçµæé åã«æé»ã«ãªããžã§ã¯ããæ§ç¯ãã
- ãã¹ããããã®ããšã¯äŸãã°ã¯ã©ã¹ã¡ã³ããé åã®èŠçŽ ã®ããš
- ãã¹ããããã®ãå«ããŠãçµæé åã«æé»ã«ãªããžã§ã¯ããæ§ç¯ãã
ãŸãããããã®æäœã«éãããchar, unsigned char, std::byteã®é
åãªããžã§ã¯ããæ§ç¯ããã®çåæéãéå§ããæäœã¯ããã®é
åãªããžã§ã¯ããå æããé åå
ã«ãã®èŠçŽ ã®ãªããžã§ã¯ããæé»çã«æ§ç¯ããã
å ±çšäœã®ã³ããŒæäœ
å ±çšäœã®ããã©ã«ãã®ã³ããŒ/ã ãŒãã³ã³ã¹ãã©ã¯ã¿ãšä»£å ¥æŒç®åã§ã¯ã次ã®ããã«ãªããžã§ã¯ããæé»çã«æ§ç¯ãã
- ã³ã³ã¹ãã©ã¯ã¿
- ã³ããŒå
ãªããžã§ã¯ãã«ãã¹ãããåãªããžã§ã¯ãã«å¯ŸããŠãã³ããŒå
å
ã§å¯Ÿå¿ãããªããžã§ã¯ã
oã- ãµããªããžã§ã¯ãã®å Žå : ç¹å®ãã
- ãã以å€ã®å Žå : æé»çã«æ§ç¯ãã
- å¥ã®ãªããžã§ã¯ãã«ã¹ãã¬ãŒãžãæäŸããŠããå Žåããµããªããžã§ã¯ãã®ãµããªããžã§ã¯ããªã©
oã®çåæéã¯ã³ããŒã®åã«éå§ããã
- ã³ããŒå
ãªããžã§ã¯ãã«ãã¹ãããåãªããžã§ã¯ãã«å¯ŸããŠãã³ããŒå
å
ã§å¯Ÿå¿ãããªããžã§ã¯ã
- 代å
¥æŒç®å
- ä»£å ¥å ãšä»£å ¥å ãåããªããžã§ã¯ãã§ã¯ãªãå Žå
- ã³ããŒå
ãªããžã§ã¯ãã«ãã¹ãããåãªããžã§ã¯ãã«å¯ŸããŠãã³ããŒå
å
ã§å¯Ÿå¿ãããªããžã§ã¯ã
oãæé»çã«æ§ç¯ãã oã®çåæéã¯ã³ããŒã®åã«éå§ããã
ã©ã¡ãã®å Žåããã³ããŒå ã§çåæéå ã«ãããªããžã§ã¯ããã³ããŒå ã§ïŒå¯èœãªãïŒæé»çã«æ§ç¯ãããã
ã¯ã©ã¹åãã¡ã³ããšããŠä¿æããå Žåãªã©ãããã©ã«ãã®ã³ã³ã¹ãã©ã¯ã¿/代å
¥æŒç®åãdeleteãããŠããå Žåã¯ããã¯è¡ãããªãã
æé»çãªãªããžã§ã¯ãæ§ç¯
ãªããžã§ã¯ããæé»çã«æ§ç¯ããæäœã§ã¯ãããããããšã§ããã°ã©ã ãå®çŸ©ãããæ¯ãèããããããã«ãªãïŒããªãã¡ãæªå®çŸ©åäœãåé¿ã§ããïŒå Žåã«ãimplicit-lifetime typesã®0å以äžã®ãªããžã§ã¯ããæé»çã«æ§ç¯ããã®çåæéãéå§ãããããã®ãããªãæé»çãªãªããžã§ã¯ãæ§ç¯ã«ãã£ãŠããã°ã©ã ã«å®çŸ©ãããæ¯ãèãããããããªããžã§ã¯ãã®éåã1ã€ãååšããªãå Žåã¯æªå®çŸ©åäœãåŒãèµ·ããïŒããã¯ä»ãŸã§éãïŒãéã«ããã®ãããªãªããžã§ã¯ãã®éåãè€æ°ååšããŠããå Žåã¯ãã©ã®ãªããžã§ã¯ããæé»çã«æ§ç¯ããããã¯æªèŠå®ïŒããã¯ãéœåºŠé©åãªãªããžã§ã¯ããéžæããæ§ç¯ãããããšãæå³ããŠããïŒã
æé»çãªãªããžã§ã¯ãæ§ç¯ãè¡ãããå Žåããã®ãµããªããžã§ã¯ãã®implicit-lifetime typesã®ãªããžã§ã¯ããæé»çã«æ§ç¯ããçåæéãéå§ãããããimplicit-lifetime typesã§ã¯ãªããªããžã§ã¯ãã¯æé»çã«æ§ç¯ãããªãããæç€ºçãªåæåãå¿ èŠãšãªãã
æé»çãªãªããžã§ã¯ãæ§ç¯ãè¡ããªããŠãããã°ã©ã ãå®çŸ©ãããæ¯ãèããããïŒæªå®çŸ©åäœãšãªããªãïŒå Žåãå¯Ÿè±¡ã®æäœã¯æé»çã«ãªããžã§ã¯ããæ§ç¯ãããéåžžã®å¹æã®ã¿ãããããã
ããã«ããªããžã§ã¯ããæé»çã«æ§ç¯ããæäœã®å ã¡ã¢ãªã確ä¿ãã颿°çäžéšã®æäœã§ã¯ãæé»çãªãªããžã§ã¯ãæ§ç¯ã«ãã£ãŠäœæããããªããžã§ã¯ããæãé©åãªãã€ã³ã¿ãè¿ãããšãèŠå®ãããããããã®æäœã«ãããŠã¯ããã®ãã€ã³ã¿å€ãè¿ãããšã§ããã°ã©ã ãå®çŸ©ãããæ¯ãèããããããã«ãªãå Žåã«ãæå®ãããé åã®å é ã¢ãã¬ã¹ãã¢ãã¬ã¹ãšããæé»çã«æ§ç¯ããããªããžã§ã¯ãã®1ã€ãéžæãããã®ãªããžã§ã¯ããæããã€ã³ã¿å€ãçæããããè¿ãããã®ãããªãããã°ã©ã ã«å®çŸ©ãããæ¯ãèãããããããããªãã€ã³ã¿å€ãååšããªãå Žåã¯æªå®çŸ©åäœãåŒãèµ·ãããéã«ããã®ãããªãã€ã³ã¿å€ãè€æ°ååšããŠããå Žåã¯ãã©ã®ãã€ã³ã¿å€ãçæããããã¯æªèŠå®ã
ãã®ãããªãã€ã³ã¿çæãè¡ããªããŠãããã°ã©ã ãå®çŸ©ãããæ¯ãèããããå Žåããã®ãããªãã€ã³ã¿å€ã¯çæããããå¯Ÿè±¡ã®æäœã¯éåžžã®ãã€ã³ã¿å€ãè¿ãã
æ¬äŒŒãã¹ãã©ã¯ã¿åŒã³åºãã«ããçåæéã®çµäº
äžéšã®æèã§ã¯ãã¹ã«ã©åã®ãªããžã§ã¯ãã«å¯ŸããŠãã¹ãã©ã¯ã¿åŒã³åºããè¡ãããšãã§ãããã®å Žåã®ãã¹ãã©ã¯ã¿åŒã³åºãã®ããšãæ¬äŒŒãã¹ãã©ã¯ã¿åŒã³åºãïŒpseudo-destructor callïŒãšåŒã¶ã
C++17ãŸã§ãæ¬äŒŒãã¹ãã©ã¯ã¿åŒã³åºãã«ã¯äœã®å¹æããªãã£ãïŒãã³ãã¬ãŒãã®æèã§ã¯ã©ã¹åãšã®æ§æäžã®äºææ§ãåãããã®ãã®ã§ãããªãã£ãïŒããC++20ããã¯æ¬äŒŒãã¹ãã©ã¯ã¿åŒã³åºãã¯ãã®ã¹ã«ã©åãªããžã§ã¯ãã®çåæéãçµäºãããããšãèŠå®ãããã
constexpr int f() {
int a = 123;
using T = int;
// æ¬äŒŒãã¹ãã©ã¯ã¿åŒã³åºã
// C++20ããã¯aã®çåæéãçµäºããã
// C++17ãŸã§ã¯äœã广ããªã
a.~T();
return a; // C++20ããã¯UBãC++17ãŸã§ã¯123ãè¿ã
}
static_assert(f() == 123); // C++20ããã¯UBãèµ·ããããäžé©æ ŒãC++17以åã¯é©æ Œ
ããã«äŒŽããdestroy_at()ãªã©ã®æ¬äŒŒãã¹ãã©ã¯ã¿åŒã³åºããšç䟡ã®ããšãè¡ãã©ã€ãã©ãªæ©èœã«ãããŠããã¹ã«ã©åã®ãªããžã§ã¯ãã®çåæéãçµäºãããããã«ãªãã
ãããã®å€æŽã®åœ±é¿
ãããã®å€æŽã¯ãããŸã§ãªããžã§ã¯ãçåæéã«é¢ããèŠåã倿Žããã ãã«éããããã®åœ±é¿ã¯ã³ã³ãã€ã©çã®å®è£ ã®ãªããžã§ã¯ãçåæéã®èªèãå€ããã ãã§ãããããã«ãã£ãŠãä»ãŸã§æªå®çŸ©åäœãšãªã£ãŠããã³ãŒããæªå®çŸ©åäœã§ã¯ãªããªããæªå®çŸ©åäœãããªã¬ãŒãšããæé©åãåããå¯èœæ§ãå°æ¥ã«ããã£ãŠåãé€ãããããšã«ãªãïŒãã ããæ¬äŒŒãã¹ãã©ã¯ã¿åŒã³åºãåšãã®å€æŽã ãã¯ãæªå®çŸ©åäœã§ã¯ãªãã£ãã³ãŒããæªå®çŸ©åäœã«ãããïŒã
ãããã£ãŠããããã®å€æŽã«ãã£ãŠå®è¡æã«äœããã¹ãããšãå¢ããããã§ã¯ãªããæé»çãªãªããžã§ã¯ãæ§ç¯ã¯å®éã«ã³ã³ã¹ãã©ã¯ã¿ãåŒãã ãäœãåæåãè¡ããã®ã§ã¯ãªãããæ¬äŒŒãã¹ãã©ã¯ã¿åŒã³åºããå®è¡æã«äœããããããã«ãªãããã§ããªãã
以åã®åé¡ã®ä¿®æ£äŸ
malloc()/ operator new
// Xã¯implicit-lifetime class types
struct X {
int a;
int b;
};
X *make_x() {
// åŸç¶ã®Xã®ã¡ã³ãã¢ã¯ã»ã¹ãå®çŸ©ãããæ¯ãèããšããããã«
// malloc()ã¯ã¡ã¢ãªã®ç¢ºä¿ãšãšãã«Xã®ãªããžã§ã¯ãïŒãšã¡ã³ããªããžã§ã¯ãïŒãæé»çã«æ§ç¯ãã
// ãããŠãæ§ç¯ãããXã®ãªããžã§ã¯ããžã®é©åãªãã€ã³ã¿ãè¿ã
X *p = (X*)malloc(sizeof(struct X));
// pã®é åã«ã¯Xã®ãªããžã§ã¯ããæé»çã«æ§ç¯ãããŠãã
p->a = 1; // â
ok
p->b = 2; // â
ok
return p;
}
// newæŒç®åã䜿çšããå Žå
X *make_x() {
// åŸç¶ã®Xã®ã¡ã³ãã¢ã¯ã»ã¹ãå®çŸ©ãããæ¯ãèããšããããã«
// operator new()ã¯ã¡ã¢ãªã®ç¢ºä¿ãšãšãã«Xã®ãªããžã§ã¯ãïŒãšã¡ã³ããªããžã§ã¯ãïŒãæé»çã«æ§ç¯ãã
// ãããŠãæ§ç¯ãããXã®ãªããžã§ã¯ããžã®é©åãªãã€ã³ã¿ãè¿ã
X *p = (X*)::operator new(sizeof(struct X));
// pã®é åã«ã¯Xã®ãªããžã§ã¯ããæé»çã«æ§ç¯ãããŠãã
p->a = 1; // â
ok
p->b = 2; // â
ok
return p;
}
å ±çšäœã®ã³ããŒ
union U {
int n;
float f;
};
float pun(int n) {
// U::nã®çåæéãéå§
U u = {.n = n};
// ãã®ã³ããŒã§ã¯uã®ãªããžã§ã¯ã衚çŸãã³ããŒããããšãšãã«
// uã®ã¢ã¯ãã£ãã¡ã³ãã«å¯Ÿå¿ããã¡ã³ããã³ããŒå
ã§ã¢ã¯ãã£ããšãªã
U u2 = u;
// u2.fã¯éã¢ã¯ãã£ã
return u2.f; // ð UB
}
å ±çšäœã®ã³ããŒã«ãããŠã¯ãããŸã§ã³ããŒå ã§çåæéå ã«ãã£ããªããžã§ã¯ãã«å¯Ÿå¿ãããªããžã§ã¯ããã³ããŒå ã§ãçåæéå ã«ããããšãä¿èšŒãããã ãã§ãtype-punningã®ãããªããšãå¯èœã«ããããã§ã¯ãªãã
int f(int n) {
U u = {.n = n};
U u2 = u;
// ãããªãok
return u2.n; // â
ok
}
ãã€ãé åã®èªã¿èŸŒã¿
// äœããã€ãåã¹ããªãŒã ãåãåã£ãŠåŠçãã颿°ãšãã
void process(Stream *stream) {
// ãã€ãé
åã®èªã¿åºã
std::unique_ptr<char[]> buffer = stream->read();
// å
é ãã€ãã®ç¶æ
ã«ãã£ãŠåå²
if (buffer[0] == FOO) {
process_foo(reinterpret_cast<Foo*>(buffer.get())); // #1
} else {
process_bar(reinterpret_cast<Bar*>(buffer.get())); // #2
}
}
FooãBarãimplicit-lifetime typesã ãšããŠããã®ã³ãŒãã«å¯ŸããŠStream::read()ãæ¬¡ã®ããã«å®è£
ãããŠããå Žå
unique_ptr<char[]> Stream::read() {
// ... determine data size ...
unique_ptr<char[]> buffer(new char[N]);
// ... copy data into buffer ...
return buffer;
}
ãã®read()å
ã®new char[N]ã«ãã£ãŠåŒã°ããoperator new[]ã«ãã£ãŠFoo/Barã®ãªããžã§ã¯ããæé»çã«æ§ç¯ãããããã®å Žåãbuffer[0] == FOOã«ããåå²ã«ãã£ãŠããã°ã©ã ã«å®çŸ©ãããæ¯ãèãããããããªããžã§ã¯ãã¯ãFooãšBarã®ãªããžã§ã¯ããšããŠ2ã€ååšããããããã£ãŠãããã§ã¯å
é ãã€ãã®ç¶æ
ã«å¿ããŠé©åãªãªããžã§ã¯ããæ§ç¯ãããïŒããããããšã§ããã°ã©ã ã«å®çŸ©ãããæ¯ãèããããããïŒãããprocess()å
ã§ã¯æªå®çŸ©åäœã¯åé¿ãããã
ãã ããprocess()å
ã®ååå²ã«ãããŠã¯ãè¿ãããbufferãã€ã³ã¿ïŒchar(*)[]ïŒããããããã®å Žåã§é©åãªãªããžã§ã¯ãïŒFoo/BarïŒãžã®ãã€ã³ã¿ããstd::launder()ãçšããŠååŸããå¿
èŠãããã
reinterpret_castã¯ãã€ã³ã¿åã®å€æã®ã¿ãè¡ãããå倿ã ãã§ã¯ãã®ãã€ã³ã¿ã¯ãã®é åã§çåæéå
ã«ãããªããžã§ã¯ããšå¿
ããããªã³ã¯ããªããstd::launder()ã¯ãæž¡ããããã€ã³ã¿ã®é åã§çåæéå
ã«ãããªããžã§ã¯ããžã®ãã€ã³ã¿ãçæããŠè¿ã颿°ã§ããããããçšããããšã§æé»çã«æ§ç¯ããããªããžã§ã¯ããžã®é©åãªãã€ã³ã¿ãåŸãããšãã§ããã
åçé åã®å®è£
ãã®äŸã§ã¯ãreserve()å
newbufåã³ãããä¿åããŠããVec::bufã®é åã«T[]ïŒTã®é
ååïŒãšchar[]ã®ãªããžã§ã¯ããæé»çã«æ§ç¯ãããåæã«çåæéå
ã«ããããšã§ãåé¡ïŒé
åãªããžã§ã¯ããæããªããã€ã³ã¿ã®ã€ãã¬ãŒã¿ãšããŠã®äœ¿çšïŒã¯è§£æ¶ãããã
ãã ããnewbufåã³Vec::bufããéœåºŠé©åãªãªããžã§ã¯ããžã®ãã€ã³ã¿ãåŸãã®ã«std::launder()ãé©åã«äœ¿çšããå¿
èŠãããã
ãã®æ©èœãå¿ èŠã«ãªã£ãèæ¯ã»çµç·¯
äŸã«äžãã£ãŠãããããªã³ãŒãã¯Cèšèªã§ã¯äžè¬çãªæäœã§ãããCã§ã¯åé¡ããªãããã®ãããªã³ãŒãã¯CãšC++ã®ã³ãŒãå ±æéšåã§C++ã³ãŒããšããŠçŸããå¯èœæ§ãããããã®å Žåã«ã¯æªå®çŸ©åäœãåŒãèµ·ããã
ãŸããåçé
åã®äŸãªã©ã¯ãstd::vectorã®å®è£
ã«ãããŠåé¡ãšãªãããšã§ãããã¯å®å
šã«C++ã®ã³ãŒãã§ãããªããC++ããµããŒãããŠãªãããšãè¡ãããšã«ãªã£ãŠããŸãã
ãããã®åé¡ã¯ã圱é¿ãåããã³ãŒããå€ãããããå®è£ ã¯ãããæé©åã«çšãããã¯ããªããšèãããããããå®éã«ã¯åé¡ãšãªããªãå¯èœæ§ãé«ãã£ãããããããããã®ããæžãããŠããã³ãŒããC++ããµããŒãããŠããªããšããå¥åŠãªç¶æ³ãæ¹åãããããæé»çãªãªããžã§ã¯ãæ§ç¯ãšãã仿§ãå°å ¥ãããã
æ€èšãããã»ãã®éžæè¢
äžèšã®åé¡ã解決ããããã®æ¹æ³ãšããŠãæé»çãªãªããžã§ã¯ãæ§ç¯ä»¥å€ã«
- åé¡ãšãªãæäœãç¡æ¡ä»¶ã§åæ³å
- ã©ã€ãã©ãªé¢æ°ã远å ããŠããããä»ããŠã³ã³ãã€ã©ã«æå³ãäŒé
std::spanãç¹å¥æ±ãããŠãé¢é£ããæäœãåæ³å
ãªã©ãèæ¡ãããŠããã
æçµçã«ã¯ãC++ã®ãªããžã§ã¯ãã¢ãã«ãä¿®æ£ããæé»çãªãªããžã§ã¯ãæ§ç¯ã«ãã£ãŠãã®åé¡ãè§£æ¶ããããšã«ãªã£ãã
ãªãã2çªç®ã®ç¹æ®ãªã©ã€ãã©ãªé¢æ°ãC++23ã§std::start_lifetime_as()ãšããŠè¿œå ãããŠããã
é¢é£é ç®
åç §
- P0593R6 Implicit creation of objects for low-level object manipulation
- P0593R0 What to do with buffers that are not arrays, and undefined behavior thereof?
- CWG Issue 2325.
std::launderand reuse of character buffers - CWG Issue 2605. Implicit-lifetime aggregates
- P1839R5 Accessing Object Representations