[英]Using initialized variable after placement new from the constructor tripping UB?
Disregarding whether the following can be achieved through other, more safe constructs - I'm simply interested in whether or not the following results in a well-defined output. 不管以下内容是否可以通过其他更安全的结构来实现-我只是对以下内容是否会产生明确定义的输出感兴趣。
Assume you have a struct A: 假设您有一个结构A:
struct A {
Foo* foo;
}
And a struct B inheriting from it: 还有一个结构B继承自它:
struct B : A {
B() {
foo->some_function(); // UB
}
}
Sure enough if you were creating a B
instance the normal way you'd trip UB, however... 当然,如果您以正常的方式创建UB来创建
B
实例,那么...
template<typename R>
R make_A() { // This acts like a constructor for As
static_assert(std::is_base_of<A, R>::value, "R must derive from A");
char r[sizeof(R)];
((R*)r)->foo = returns_some_valid_foo();
new (r) R;
return *((R*)r);
}
B b1; // Blows up (Could you somehow prevent this from compiling without changing B?)
B b2 = make_A<B>(); // Works fine?
Sheepishly assuming that C++ works like C somewhere under the hood, I'm guessing that this would be similar to having a struct instance in C, initializing it by hand, and then calling some method (in this case B's constructor) on the finished product. 令人毛骨悚然地假设C ++在幕后某个地方像C一样工作,我猜测这类似于在C中拥有一个struct实例,手动对其进行初始化,然后在最终产品上调用某种方法(在这种情况下为B的构造函数) 。
Again, I'm not interested in whether you should do this or not, it's just a technical question. 同样,我对您是否应该执行此操作不感兴趣,这只是一个技术问题。
EDIT: 编辑:
If you wonder what this could be useful for, I could use it to pull out values into a plain struct from, say, a configuration file in a really terse manner. 如果您想知道这可能有什么用,我可以使用它以非常简洁的方式将值从(例如)配置文件中提取到纯结构中。 Yes it does use macros but call it a stub until C++ gets compile time reflection:
是的,它确实使用宏,但是将其称为存根,直到C ++反映了编译时间:
#define config_key($x, $def) $x = foo->get<decltype($x)>(#$x, ($def))
struct Record : A {
int config_key(a, 3); // Second parameter is default value
string config_key(b, "something");
}
auto record = make_A<Record>();
(Using A and foo here to stay consistent with what I wrote above, make_A is actually part of a class that does config) (在这里使用A和foo与我上面写的保持一致,make_A实际上是进行配置的类的一部分)
This: 这个:
((R*)r)->foo = returns_some_valid_foo();
is undefined behavior. 是未定义的行为。 There is no object of type
R
at r
. 在
r
处没有类型R
对象。 Full stop. 句号 If you flip the two lines so that you create the
R
first, then you're fine (modulo r
being insufficiently aligned). 如果翻转两条线以便首先创建
R
,那么就没问题了(模数r
对齐不充分)。
Or really, just: 或者说真的:
R r;
r.foo = returns_some_valid_foo();
return r;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.