2

応答を書く際に、constポインターがどのように機能するかについての私の仮定に異議を唱えるいくつかのコードを書きました。constポインターは削除関数で削除できないと思っていましたが、以下のコードからわかるように、そうではありません。

#include <new>
#include <string.h>

class TestA
{
    private:
        char *Array;
    public:
        TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
        ~TestA(){if(Array != NULL){ delete [] Array;} }

        char * const GetArray(){ return Array; }
};

int main()
{
    TestA Temp;
    printf("%s\n",Temp.GetArray());
    Temp.GetArray()[0] = ' '; //You can still modify the chars in the array, user has access
    Temp.GetArray()[1] = ' '; 
    printf("%s\n",Temp.GetArray());
    //Temp.GetArray() = NULL //This doesn't work

    delete [] Temp.GetArray(); //This works?! How do I prevent this?
}

私の質問は、削除関数が何らかの苦情や例外をスローすることで、ポインターを削除できないようにしながら、ユーザーアクセスをポインターに渡す(ユーザーがchar配列のように使用できるようにする)にはどうすればよいですか?

4

5 に答える 5

6

ユーザーがdelete[]から取得していないポインターを使用している場合new[]は、ヒントバットで頭を上に向けて叩きます。

ポインターを逆参照できるが、delete に渡してはならない理由はたくさんあります。

  • 他の誰かが削除します。
  • ブロックの始まりではありません。
  • mallocまたは他の非newアロケータからのものです。
  • 動的ではなく、静的な寿命があります。
  • 自動有効期間がある場合。

これらのいくつかは、実行時に例外として現れます。他のものは、後でクラッシュを引き起こします。標準によると、すべて「未定義の動作」です。

delete特に明記されていない限り、ポインタは への引数として使用できないと仮定する必要があります。

初級レベルのプログラマーがこの間違いを犯している場合は、彼らを教育してください。「経験豊富な」開発者がそれを行っている場合は、履歴書に嘘をついたとして解雇してください。


彼らがそれをしたときにそれを傷つけたいだけなら、配列を必要以上に1つ大きく割り当ててくださいreturn Array + 1;. 彼らが を使おうとすると、すべてが爆発しますdelete[]

実際の使用法は、delete への偽の呼び出し内でプログラムがクラッシュする可能性が (より高く) あり、問題のある関数がコール スタックに残っていることです。オリジナルはおそらくしばらくの間実行を続け、最終的に無害なコードでクラッシュします。したがって、これは愚かなユーザーを捕まえるのに役立ちます。

于 2011-10-10T17:14:01.237 に答える
5
delete [] Temp.GetArray(); //This works?! How do I prevent this?

char*それが戻るか、他のポインタ型である限り、それを防ぐことはできません。次のすべてがC++で完全に有効であるため、deleteステートメントの式がであるかどうかは関係ありません。const

char *pc = f(); 
delete [] pc;  //ok

const char *pc = g(); 
delete [] pc; //ok

char * const pc = h(); 
delete [] pc; //ok

const char * const pc = k(); 
delete [] pc; //ok

ただし、これを変更すると:

char *Array;

これに

std::vector<char> Array;

そして、次のように返すことで、必要なことを達成できます。

std::vector<char> & GetArray() { return Array; }

結論は:

C ++では、動的配列を使用しないstd::vector<T>非常に強い理由がない限り、動的配列のデフォルトの選択は次のようになります。

于 2011-10-10T16:54:57.460 に答える
1

const は何の効果もありません。const char へのポインターではなく、const ポインターを返しています。これが必要です。代わりにベクトルを使用することに関する Nawaz の推奨事項も参照してください。

于 2011-10-10T17:11:29.020 に答える
1

実際にできることのほとんどは、 の許容オペランドではないものを返すことですdelete。これは、RAII オブジェクト (std::vector や std::array など) にすることも、参照にすることもできます (状況に応じて、どちらかが適切な場合があります)。

[残念ながら、C++ では、プログラマーはあらゆる種類の卑劣なことを行うことができます。

于 2011-10-10T17:42:19.823 に答える
0

愚かさを完全にブロックすることはできませんが、実際の配列ポインターを返す代わりにアクセスメカニズムを使用することで、愚かさを少し抑えることができます。

char& operator[](size_t index) { return Array[index]; }

これは、それを char 配列のように扱う機能には対応していませんが、指摘されているように、そのポインターを明らかにすると、(悪い) プログラマーは自由に削除を実行できます。

于 2011-10-10T19:29:34.067 に答える