簡體   English   中英

C ++中的指針分配

[英]Pointer assignment in c++

我有一個簡單的結構來保存兩個const double s。

struct Scale {
    const double SCALE_X, SCALE_Y;

    Scale(double, double);
};

Scale::Scale(double sx, double sy) :
SCALE_X(sx), SCALE_Y(sy) {
}

我有此函數返回一個布爾值作為確認,並將傳遞的oscale指針設置為在內部找到的任何計算值。

bool FindSequence(Scale* oscale) {
    // ...
    *oscale = Scale(sx, sy);
    // ...
    return true;
}

正在使用:

Scale *scale;
if (FindSequence(scale)) {
    std::cout << "Yes" << std::endl;
}

編譯日志:

photon.cpp:286:14: error: use of deleted function 'photon::Scale& photon::Scale::operator=(photon::Scale&&)'
      *oscale = Scale(sx, sy);
              ^
In file included from photon.h:5:0,
                 from photon.cpp:4:
globals.h:76:9: note: 'photon::Scale& photon::Scale::operator=(photon::Scale&&)' is implicitly deleted because the default definition would be ill-formed:
  struct Scale {
         ^
globals.h:76:9: error: non-static const member 'const double photon::Scale::SCALE_X', can't use default assignment operator
globals.h:76:9: error: non-static const member 'const double photon::Scale::SCALE_Y', can't use default assignment operator

我是否必須重寫operator =? 是因為Scale結構是不可變的嗎? 我究竟做錯了什么?

這里有幾個問題。 我將一一介紹。

const double SCALE_X, SCALE_Y;

這是您問題的主要根源。 如果類具有const成員,則編譯器將不會生成副本構造函數或副本賦值運算符; 您必須自己生成它們。

但是,我認為這些成員甚至都不應該是const 如果某人具有Scale對象,則他們應該能夠更改其值,但是如果他們具有const Scale對象,則他們將無法更改,因為在一個對象上訪問時,所有(非mutable )數據成員都“成為” constconst對象。

換句話說,讓類的使用者決定他們是否要讓實例為只讀; const Scale對象應該是可變的!

通過這一更改,編譯器將能夠生成合理的副本構造函數和合理的副本賦值運算符,從而消除特定的錯誤。

但是,您在這里確實還有另一個錯誤:

Scale *scale;
if (FindSequence(scale)) {

您正在傳遞未初始化的指針。 一旦FindSequence()取消引用此指針,就會調用未定義的行為,並且您的程序可能會崩潰。

通常,您可以使用引用進行此操作:

bool FindSequence(Scale & oscale) {

然后,調用代碼變成這個(只需刪除* ):

Scale scale;
if (FindSequence(scale)) {

但是要做到這一點,您將需要一個默認的構造函數。 一個明智的選擇是將其初始化為零:

Scale::Scale() : SCALE_X(0), SCALE_Y(0) { }

(或者,您可以只執行Scale scale(0, 0); ;。)

應用這三個更改,編譯器應該克服這些問題。 (當然,它可能會遇到其他問題,但是這些更改將解決您的問題。)

這里有兩件事要注意

第一個編譯器不會為不知道如何分配的類(即包含const和引用成員的類)生成assigment運算符。

其次,您試圖取消引用未初始化的指針,這很糟糕。

我會添加,作為一個額外的注意,如果你真的想有const成員和一個初始化函數,那么這樣做是安置新方式:

bool FindSequence(Scale* oscale) {
    // ...
    oscale = new (oscale) Scale(sx, sy);
    // ...
    return true;
}

這使用您的Scale構造函數初始化指向的對象,而不是賦值運算符,從而避免了需要由編譯器生成的運算符。

正如其他人指出的那樣,您的代碼隨后會遇到未定義的行為,因為您將未初始化的指針傳遞給FindSequence函數。 您可能的意思是這樣的:

Scale scale(0.0, 0.0);
if (FindSequence(&scale)) {
    std::cout << "Yes" << std::endl;
}

有人會認為這是一個壞主意,因為它允許您在初始化后更改const對象,而且我希望您的編譯器可以在那些const double成員不變的假設下嘗試進行優化,因此您可能如果嘗試此操作,則會看到奇怪的行為。

暫無
暫無

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

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