[英]Reset directly the content of a struct
我已經實現了一個 function 來重置指針指向的結構的內容:
template <typename Struct>
void initialize(Struct* s)
{
*s = Struct{};
}
當Struct
變大(超過 10K)時,我會遇到性能問題,因為Struct
是在堆棧中創建的,然后分配給*s
。 我想知道我是否可以改進它:
Struct{}
object 的情況下直接初始化*s
?Struct
的大小並將其構建在堆中(如果它很大)?先感謝您
首先,您可能應該使用參考; 不是指針。 這樣做的目的是避免 null 間接錯誤。
如果 class 是平凡的並且值初始化為零(這通常是大多數平凡類型的情況),那么優化器應該將您的 function 編譯為對memset
的調用,而無需初始化臨時 ZA668CFDE691ACZF456。 所以在這種情況下應該沒有理由擔心。
您可以顯式調用memset
,盡管從技術上講,如果 class 包含某些類型(例如,null 指針不一定具有零表示),這在技術上不能移植到外來系統。
是否可以在沒有臨時 Struct{} object 的情況下直接初始化 *s?
是的,如果您願意更改 function 的要求。 目前它適用於默認可構造和可移動分配的類。
如果直接修改指向的 object,則可以避免創建臨時 object。 在以下示例中,沒有創建Struct
類型的臨時對象:
constexpr void
initialize(Struct& s)
{
s.member1 = T1{};
s.member2 = T2{};
為了使其通用,可以在成員 function 中執行操作。 因此,您可以指定一個要求,即指向的 class 具有一個具有特定名稱且沒有參數的成員 function:
s.clear();
您可以將這兩種方法組合用於它們適用的類型:
template<class Struct>
constexpr void
initialize(Struct& s)
{
if constexpr (std::is_trivially_copyable_v<Struct>) {
// alternative 1, if you trust your optimiser
s = Struct{};
// alternative 2, if you doubt the quality of the optimiser
// technically may have different meaning on exotic systems
std::memset(&s, 0, sizeof s);
} else {
s.clear();
}
}
如果您需要它來處理一些不符合這兩個要求的類,那么您需要專門化模板。
我是否應該評估 Struct 的大小並將其構建在堆中(如果它很大 [10K])?
您通常應該避免完全擁有這么大的公共課程。 如果您需要如此大的存儲空間,您可以將其包裝在動態分配的類型中。 像這樣的東西:
class Struct
{
private:
struct VeryLarge{/.../};
std::unique_ptr<VeryLarge> storage;
public:
// public interface
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.