簡體   English   中英

為什么c ++構造函數在作為靜態成員變量出現時未被調用?

[英]why the c++ constructor was not called when it appear as the static member variable?

我有一個奇怪的問題,

聲明一個靜態成員變量,其名稱在A類中為B類。 並在cpp文件中初始化。 但B類的構造函數從未被調用過。 我嘗試使用一些小測試,可以正常調用測試構造函數。 所以我們的生產系統很奇怪。

這樣的代碼,在hpp中

class Test
{
    public:
    Test()
    {
        ofstream file("/tmp/wup.txt",ios::app);
        file << "wup in test" << endl;
        file.close();
    }
};

//## An extended personality
class TsdNAExtPersonality : public TsdNAPersonality{
public:

  TsdNAExtPersonality(
        s_gg62_personRec * gg62Header,
                   TsdNAFunctionType requiredFunctionType);
private:
  static Test test;

public:
  TsdNAExtPersonality( string * personalityFile, TsdNAFunctionType requiredFunctionType);
};

在我初始化的另一個cpp文件中

Test TsdNAExtPersonality::test;

我曾嘗試過多種方式,但我發現所有方法都是無用的。

  1. 沒有將變量設置為成員變量,但是全局變量==>也無法輸出
  2. 將成員變量更改為指針並將初始化方式更改為使用new ==> no

環境是HP-UX,編譯是aCC

所以我的問題是:

  1. 是否有任何編譯選項會影響變量? 換句話說,所有靜態變量都不會被初始化。

  2. 從C ++的標准來看,它應該在庫加載時調用,對吧?

  3. 我使用相同的方式放置另一個靜態int值,它可以初始化。 但是沒有調用類構造函數,非常奇怪。

  4. 在我的代碼中有任何錯誤嗎?

從C ++的標准來看,它應該在庫加載時調用,對吧?

否。具有靜態存儲持續時間的對象的動態初始化保證在執行在同一翻譯單元中定義的任何功能之前發生。 如果沒有這樣的功能,或者你的程序從不調用它們,那么就不能保證它會被初始化。

我使用相同的方式放置另一個靜態int值,它可以初始化。 但是沒有調用類構造函數,非常奇怪。

只要其初始化為常量, int變量在程序啟動之前靜態初始化。

是否有任何編譯選項會影響變量?

不是我所知道的,但我對你的平台並不熟悉。 您可以通過在函數中進行范圍設置來更好地控制對象的創建:

static Test & test() {
    static Test test;
    return test;
}

現在可以保證在第一次調用函數時進行初始化。 當然,你需要記住在某個時候調用它。

C ++程序的啟動和關閉是一些灰色區域,因為您不清楚您已經使用了多少代碼(因為它已經被初始化)以及還有多少已經開始。 在關閉時,析構函數也會發生同樣的情況......當您的靜態實例被銷毀時,尚不清楚有多少個子系統已經關閉。

此外,您永遠不應該對可能失敗的任何事情使用靜態初始化,在開始之前或在main結束之后進行調試可能非常困難。

另請注意,未定義靜態初始化的順序(相對於同一編譯單元中的其他靜態除外),它可能會從一個編譯更改為下一個編譯。 這意味着您可能對工作程序感到滿意,直到出於某種奇怪的原因,您獲得了不同的初始化順序,並且在代碼中沒有任何相關更改的情況下停止工作。

對於非常簡單的事情使用靜態初始化是可以的,因為其他任何事情都沒有,你應該做適當的控制初始化。

C ++中的靜態初始化是:

  • 零初始化
  • 常量初始化
  • 動態初始化

因此,最好的選擇是在第一次函數調用時初始化:

int fn() {
    static int result = 42;
    return result;
}

編輯

如果要在main之前初始化:

struct Initialize { 
    Initialize() { fn(); }
}

Initialize initialize;

我認為您的編譯器中存在錯誤。

在linux / g ++上運行這個簡單的代碼可以得到預期的結果:

#include <iostream>

using namespace std;

class A
{
    public:
        A() { cout << "Hallo" << endl; }
};

class B
{
    public:
    static A a;
};

A B::a;    // < here the constructor must be called!

int main()
{
   cout << "Main runs" << endl;
   return 0;
}

結果是:

Hallo
Main runs

構造靜態數據成員時必須調用構造函數(上面的注釋行)。

暫無
暫無

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

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