簡體   English   中英

如何在 C++ 中將結構初始化為 0

[英]How to initialize a struct to 0 in C++

這是一個相關的 C 答案,它在 C++ 中不起作用(作為結構的零初始化器): 將結構初始化為 0 提出的解決方案之一是:

myStruct _m1 = {0}; 

這在 C 中工作正常,但在 C++ 中不起作用。 :(:

錯誤:無法使用“int”類型的右值初始化“myScope::MyStruct”類型的成員子對象。

如何對 C++ 中的結構進行零初始化?

有關的:

  1. 在 C 中將結構初始化為 0: 將結構初始化為 0
  2. 更新:(一個相鄰但不重復的問題,結果也非常有用) 使用空花括號進行初始化

也可以看看:

  1. [相鄰相關,但適用於 C 風格 arrays,而不是結構]如何將數組的所有成員初始化為相同的值?

對於投票結束這個問題的人:

我的問題不是這個其他問題的重復( 使用空花括號初始化),因為這個其他問題不是詢問在 C++ 中初始化結構的各種方法以及為什么 C 方式不起作用,而是問為什么 C++ 關鍵字explicit破壞了他們的初始化技術之一 兩個截然不同的問題。 不重復。

我問的后續問題:

  1. 為什么不將 C++ 結構初始化為= {0}將其所有成員設置為 0?

在我們開始之前:

  1. 讓我指出,圍繞此語法的很多混淆是因為在 C 和 C++ 中,您可以使用= {0}語法將C 樣式數組的所有成員初始化為零! 請參閱此處: https://en.cppreference.com/w/c/language/array_initialization 這有效:

     // z has type int[3] and holds all zeroes, as: `{0, 0, 0}` int z[3] = {0};

    但是,該語法對於structs的工作方式不同,它們與 C 風格的 arrays 完全不同。

  2. 另請參閱我在下面寫完此答案后提出的后續問題:為什么不將 C++ 結構初始化為= {0}將其所有成員設置為 0?


回到答案:

我想通了:要編譯它,只需刪除零:

# does NOT work
myStruct _m1 = {0}; 

# works!
myStruct _m1 = {};

它現在編譯。 但是,我運行了一堆測試來檢查我的eRCaGuy_hello_world存儲庫中的struct_initialization.cpp文件中的一些內容,這並沒有將結構的所有元素初始化為零,而是將結構初始化為其默認值 要運行我的測試並親自查看,請在上面克隆我的 repo 並運行eRCaGuy_hello_world/cpp/run_struct_initialization.sh

假設你有這個結構:

typedef struct
{
    int num1 = 100;
    int num2 = -100;
    int num3;
    int num4 = 150;
} data_t;

注意:上面的typedef是我在 C 而不是 C++ 中測試這些東西時遺留下來的(當然,在 Z0D61F8370CAD1D412F80ZB84D143E1257 中不允許使用默認結構值)。 對於 C++,這是首選:

struct data_t
{
    int num1 = 100;
    int num2 = -100;
    int num3;
    int num4 = 150;
};

因此,無論我在哪里不必要地使用typedef來定義下面的結構,請忽略它。

無論如何,如果我聲明上述data_t結構之一,然后執行以下操作:

data_t d2 = {};
printf("d2.num1 = %i\nd2.num2 = %i\nd2.num3 = %i\nd2.num4 = %i\n\n",
       d2.num1, d2.num2, d2.num3, d2.num4);

... output 將是:

d2.num1 = 100
d2.num2 = -100
d2.num3 = 0
d2.num4 = 150

而且我什至不確定d2.num3是否為零,因為它已初始化為零或未初始化,並且 memory 位置恰好包含零。

如此處所述: https://en.cppreference.com/w/cpp/language/zero_initialization ,您也可以這樣做:

myStruct _m1{};

在上面的示例中,此代碼:

data_t d2{};
printf("d2.num1 = %i\nd2.num2 = %i\nd2.num3 = %i\nd2.num4 = %i\n\n",
       d2.num1, d2.num2, d2.num3, d2.num4);

...會產生與我上面顯示的相同的 output。

即使在將結構設置為= {0}確實有效的情況下,例如:

// Does NOT do what I expected! Only sets the FIRST value in the struct to zero! 
// The rest seem to use default values.
data_t d3 = {0};
printf("d3.num1 = %i\nd3.num2 = %i\nd3.num3 = %i\nd3.num4 = %i\n\n",
       d3.num1, d3.num2, d3.num3, d3.num4);

... output 仍然不是我所期望的,因為它只將第一個值設置為零:(我不明白為什么):

d3.num1 = 0
d3.num2 = -100
d3.num3 = 0
d3.num4 = 150

然而,在 C 風格的arrays上(不是結構),這些語義可以正常工作。 請在此處參考此答案( 如何將數組的所有成員初始化為相同的值? )。 因此,在使用 C++ 時,以下幾行都將 C 樣式數組的所有元素都設置為零:

uint8_t buffer[100] = {0}; // sets all elements to 0 in C OR C++
uint8_t buffer[100] = {};  // sets all elements to 0 in C++ only (won't compile in C)

因此, 經過大量實驗,看起來以下幾種方法是零初始化結構 PERIOD 的唯一方法。 如果您有不同的認識,請在此處發表評論和/或留下您自己的答案。

在 C++ 中對結構進行零初始化的唯一方法是:

  1. 明確:

     // C-style typedef'ed struct typedef struct { int num1 = 100; int num2 = -100; int num3; int num4 = 150; } data_t; // EXPLICITLY set every value to what you want, data_t d1 = {0, 0, 0; 0}. // OR (using gcc or C++20 only) data_t d2 = {,num1 = 0. ,num2 = 0. ,num3 = 0. ;num4 = 0};
  2. 使用memset()強制所有字節為零:

     data_t d3; memset(&d3, 0, sizeof(d3));
  3. 首先將所有默認值設置為零:

     // C-style typedef'ed struct typedef struct { int num1 = 0; int num2 = 0; int num3 = 0; int num4 = 0; } data_t; // Set all values to their defaults, which are zero in // this case data_t d4 = {}; // OR data_t d5{}; // same thing as above in C++ // Set the FIRST value only to zero, and all the rest // to their defaults, which are also zero in this case data_t d6 = {0};
  4. 為 C++ 結構體編寫一個構造函數

     // 1. Using an initializer list struct data { int num1; int num2; int num3; int num4; data(): num1(0), num2(0), num3(0), num4(0) {} }; data d7; // all values are zero // OR: 2. manually setting the values inside the constructor struct data { int num1; int num2; int num3; int num4; data() { num1 = 0; num2 = 0; num3 = 0; num4 = 0; } }; data d8; // all values are zero
  5. 使用沒有默認值的結構,並讓您的 object 從中創建static

     typedef struct { int num1; int num2; int num3; int num4; } data_t; // `static` forces a default initialization of zero for each // value when no other default values are set static data_t d9;
  6. 因此,如果您有一個具有非零默認值的結構,並且您想將所有值歸零,則必須明確地這樣做:這里有更多方法:

     // 1. Have a `constexpr` copy of the struct that you use to // reset other struct objects. Ex: struct data { int num1 = 1; int num2 = 7; int num3 = -10; int num4 = 55; }; constexpr data DATA_ALL_ZEROS = {0, 0, 0, 0}; // Now initialize d13 to all zeros using the above `constexpr` struct // object data d13 = DATA_ALL_ZEROS; // OR 2. Use a `zero()` member function to zero the values: struct data { int num1 = 1; int num2 = 7; int num3 = -10; int num4 = 55; zero() { num1 = 0; num2 = 0; num3 = 0; num4 = 0; } }; data d14; d14.zero();

這里最大的收獲是,其中沒有一個: data_t d{}data_t d = {}data_t d = {0} ,實際上將結構的所有成員設置為零!

  1. data_t d{}將所有值設置為結構中定義的默認值。
  2. data_t d = {}還將所有值設置為其默認值。
  3. 並且data_t d = {0}僅將 FIRST 值設置為零,並將所有其他值設置為其默認值。

所以,要明確

請注意,我寫的上述關鍵要點似乎與cppreference.com 上的文檔相矛盾,因此我提出了下面列出的后續問題,這對我的理解非常有幫助!

走得更遠

  1. 最有用我的后續問題:為什么不將 C++ 結構初始化為= {0}將其所有成員設置為 0?

參考:

  1. 很有用:
    1. https://en.cppreference.com/w/cpp/language/zero_initialization
    2. https://en.cppreference.com/w/cpp/language/aggregate_initialization
    3. https://en.cppreference.com/w/cpp/language/value_initialization
  2. 非常有用:將數組(不是結構)的所有成員初始化為相同的值:
    1. 如何將數組的所有成員初始化為相同的值?
    2. [僅限 gcc] 如何將數組的所有成員初始化為相同的值?
  3. https://github.com/ElectricRCAaircraftGuy/eRCaGuy_hello_world/blob/master/cpp/struct_initialization.cpp
    1. 克隆這個 repo 並使用cpp/run_struct_initialization.sh自己運行代碼

有關的:

  1. 初始化結構中的默認值
  2. *****[我自己的答案,它演示了任何 function 中的這種結構修改/聚合成員重新分配: leds[0] = {10, 20, 30, 40, 50}; ] Arduino 堆棧交換:初始化結構數組

一般是不可能的。 class 可能無法提供訪問所有成員的方法,在這種情況下,您可以做的最好的事情是初始化它,這將為您提供該 class 的默認版本。

C++ 中的對象能夠控制其中任何子對象的值。 因此,C++ 通常沒有強制對任何 object進行零初始化的機制。

沒有用戶提供的構造函數或默認成員初始化器的對象可以在兩種情況下進行零初始化:如果變量被聲明為static ,或者如果 object 正在被值初始化。 有多種語法會引發 object 的值初始化,包括T()T{}T t = {}; ,如適用。

但除此之外,如果 object 類型的創建者不希望它被零初始化,那么您不能將其強加於 object。 您可以要求值初始化或默認初始化,但其中任何一個是否會調用零初始化取決於類型。

在 C++ 中,對於沒有收縮器的類型(id est 可輕松構造), {}始終將所有字節初始化為零,與 C 中的{ 0 }相同。

PlainOldData pod{};

對於具有構造函數的類型,因此不是簡單可構造的,將所有字節初始化為零幾乎沒有意義,因為這些對象旨在控制它們自己的 state。 您通常想要的是默認初始化,通常可以使用{}來完成。:

Object obj{};
// or
Object obj;

您可以繞過此限制 go 並使用memset清除 memory,但請注意,它導致覆蓋 vtable 指針等問題。

memset(&obj, 0, sizeof obj); // dangerous for non-trivial objects

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM