![](/img/trans.png)
[英]Using std::move() vs. assign in constructor member initializer list
[英]Constructor initializer list vs. expensive operations
考虑一个假设的场景,其中两个类可以默认构造或相互构造,但任何一种方式都被认为是昂贵的(有意设计的例子如下):
struct PrivateKey;
struct PublicKey {
PublicKey(); // generate a random public key (1 minute)
PublicKey(const PrivateKey& b); // find a public key corresponding to a private key (1 year)
...members...
};
struct PrivateKey {
PrivateKey(); // generate a random private key (1 minute)
PrivateKey(const PublicKey& a); // find a private key corresponding to a public key (1 year)
...members...
};
(这当然可以浓缩为一个类,但问题的有效性不受影响。让我们说,为了连贯,在一个和另一个之间没有对称性。)
现在有一个结构可以保存两者的实例并需要这种交叉初始化。 但是,我们可能需要两个方向,因此初始化程序列表无法真正删除它们(它们不按列出的顺序运行,而是按成员定义的顺序运行,并且此处无法修复订单):
struct X {
PublicKey a;
PrivateKey b;
X(int): a(), b(a) { }
X(float): b(), a(b) { } // UB: a(b) happens before b is initialized
};
我当然可以尝试:
struct X {
PublicKey a;
PrivateKey b;
X(int): a(), b(a) { }
X(float): a(), b() { a = PublicKey(b); }
};
但这有多个问题,其中在X
的第二个构造函数中运行昂贵的PublicKey
默认构造只是为了立即抛出结果只是第一个。 PublicKey::PublicKey()
可能有副作用 。 两者仍然可以通过创建一个只暴露给朋友X
的廉价私有构造函数来缓解,这会使该类处于某种虚拟状态,但会抛出一些引用或常量成员, 并且该类可能无法移动 - 可分配或可交换 ,禁止任何变化在X::X(float)
的身体上。 是否有更好的模式可供遵循?
通过使用指向包含的类的指针,而不是直接嵌入包含的类,并在构造函数体内自己构造包含的对象,可以避免构造顺序问题。
struct X {
std::unique_ptr<PublicKey> a;
std::unique_ptr<PrivateKey> b;
X(int) {
a = std::make_unique<PublicKey>();
b = std::make_unique<PrivateKey>(*a);
}
X(float) {
b = std::make_unique<PrivateKey>();
a = std::make_unique<PublicKey>(*b);
}
};
如果类至少是可移动构造的,那么您应该能够这样做:
struct KeyPair
{
PublicKey a;
PrivateKey b;
KeyPair(std::pair<PublicKey, PrivateKey> &&data) :
a(std::move(data.first)),
b(std::move(data.second))
{}
};
std::pair<PublicKey, PrivateKey> computePublicFirst()
{
PublicKey a;
PrivateKey b(a);
return {std::move(a), std::move(b)};
}
std::pair<PublicKey, PrivateKey> computePrivateFirst()
{
PrivateKey b;
PublicKey a(b);
return {std::move(a), std::move(b)};
}
struct X
{
KeyPair keys;
X(int) : keys(computePublicFirst()) {}
X(float) : keys(computePrivateFirst()) {}
};
没有移动任务发生,只移动施工。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.