[英]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.