2010-11-24 6 views

答えて

54

int* test();

が、ベクトルを使用するために、 "より多くのC++" のようになります。

std::vector<int> test();

EDIT
私はいくつかの点を明確にします。あなたがC++に言及して以来、私はnew[]delete[]演算子を使うつもりですが、malloc/freeと同じです。最初のケースで

、あなたのような何か書きます:

int* test() { 
    return new int[size_needed]; 
} 

をしかし、あなたの機能のクライアントは本当にあなたが戻ってきている配列のサイズを知らないので、それは、クライアントが、素敵な考えではありませんdelete[]を呼び出して安全に割り当てを解除できます。

int* theArray = test(); 
for (size_t i; i < ???; ++i) { // I don't know what is the array size! 
    // ... 
} 
delete[] theArray; // ok. 

優れた署名はこの1つのようになります。

int* test(size_t& arraySize) { 
    array_size = 10; 
    return new int[array_size]; 
} 

そして、あなたのクライアントコードは現在、次のようになります。

size_t theSize = 0; 
int* theArray = test(theSize); 
for (size_t i; i < theSize; ++i) { // now I can safely iterate the array 
    // ... 
} 
delete[] theArray; // still ok. 

これはC++、 `のstd ::ベクトル< T>であるので、

std::vector<int> test() { 
    std::vector<int> vector(10); 
    return vector; 
} 

それがオブジェクトで処理されますので、今、あなたは、delete[]を呼び出す必要はありません、あなたは安全でそれを繰り返すことができます。

std::vector<int> v = test(); 
std::vector<int>::iterator it = v.begin(); 
for (; it != v.end(); ++it) { 
    // do your things 
} 

簡単かつ安全です。

+2

のための私は 'のstd :: vector'を返すといいよ。 –

+8

個人的には、「int * test();」を「howtoはC++メソッドで配列を返すのですか?」と返答すると思います。実際に配列を返さないことを説明しなければ誤解を招きますポインタです。 –

+0

私はいくつかの必要な明確化を加えました。 – Simone

2

関数から配列を返す場合は、関数を終了するときに値がスタックに保存されないようにする必要があります。

したがって、配列を静的にするか、メモリを割り当てます(または、それを渡しますが、最初の試みはvoidパラメータを使用します)。あなたの方法のために、私はこのようにそれを定義します

int *gnabber(){ 
    static int foo[] = {1,2,3} 
    return foo; 
} 
16

どのように私はC++の方法とどのように私はそれを宣言しなければならないの配列を返すことができますか? int [] test(void); ??

これは簡単な質問ですが、C++ではかなりのオプションがあります。まず、あなたが好むべきです...常にコンパイル時に指定した要素の数を保存する(C++ 11で導入された)しかし、多くの実行時に発生した要素、または

  • std::array<>に動的に拡張

    ...彼らは正しい動作を保証し、かなり物事を単純化し、あなたのためのメモリを管理するよう:

    std::vector<int> fn() 
    { 
        std::vector<int> x; 
        x.push_back(10); 
        return x; 
    } 
    
    std::array<int, 2> fn2() // C++11 
    { 
        return {3, 4}; 
    } 
    
    void caller() 
    { 
        std::vector<int> a = fn(); 
        const std::vector<int>& b = fn(); // extend lifetime but read-only 
                 // b valid until scope exit/return 
    
        std::array<int, 2> c = fn2(); 
        const std::array<int, 2>& d = fn2(); 
    } 
    

    constを返すと、コピーが回避されることがありますが、通常は戻り値の最適化、つまりvectorではarray - move semantics(C++ 11で導入されています) 。

    あなたは本当に一つの方法は、スペースを確保し、それを使用する機能を伝えるために、発信者のためである、(上記arrayと呼ばれる標準ライブラリクラス異なる)作り付け配列を使用する場合:

    void fn(int x[], int n) 
    { 
        for (int i = 0; i < n; ++i) 
         x[i] = n; 
    } 
    
    void caller() 
    { 
        // local space on the stack - destroyed when caller() returns 
        int x[10]; 
        fn(x, sizeof x/sizeof x[0]); 
    
        // or, use the heap, lives until delete[](p) called... 
        int* p = new int[10]; 
        fn(p, 10); 
    } 
    
    生の配列とは異なり - -

    別のオプションは、構造中に配列をラップすることです関数から値で返すことは合法です:

    struct X 
    { 
        int x[10]; 
    }; 
    
    X fn() 
    { 
        X x; 
        x.x[0] = 10; 
        // ... 
        return x; 
    } 
    
    void caller() 
    { 
        X x = fn(); 
    } 
    

    あなたが使用して立ち往生している場合は、上記で開始しますC++ 03あなたがC++ 11 std::arrayに近い何かにそれを一般化することができます:

    int* fn() 
    { 
        int* p = new int[2]; 
        p[0] = 0; 
        p[1] = 1; 
        return p; 
    } 
    
    void caller() 
    { 
        int* p = fn(); 
        // use p... 
        delete[] p; 
    } 
    

    へ:と呼ばれる機能を持っている

    template <typename T, size_t N> 
    struct array 
    { 
        T& operator[](size_t n) { return x[n]; } 
        const T& operator[](size_t n) const { return x[n]; } 
        size_t size() const { return N; } 
        // iterators, constructors etc.... 
        private: 
        T x[N]; 
    }; 
    

    別のオプションがあるヒープ上にメモリを割り当てますヒープオブジェクトの管理を簡素化するのに役立ちます。多くのC++プログラマは、オブジェクトへのポインタがスコープを離れるときに削除を確実にする「スマートポインタ」を使用します。 C++ 11では:それはboost::shared_arrayを提供します。あなたは、C++ 03の上に立ち往生している場合は

    std::shared_ptr<int> p(new int[2], [](int* p) { delete[] p; }); 
    std::unique_ptr<int[]> p(new int[3]); 
    

    、最良のオプションは、ブーストライブラリがあなたのマシン上で利用可能であるかどうかを確認することです。

    静的メモリはfn()で予約されていますが、これは安全ではありませんが、fn()への各呼び出しは前回の呼び出しからポインターを保持しているユーザーのデータを上書きします。つまり、シンプルなシングルスレッドコードでは便利で(高速な)ことができます。

    int* fn(int n) 
    { 
        static int x[2]; // clobbered by each call to fn() 
        x[0] = n; 
        x[1] = n + 1; 
        return x; // every call to fn() returns a pointer to the same static x memory 
    } 
    
    void caller() 
    { 
        int* p = fn(3); 
        // use p, hoping no other thread calls fn() meanwhile and clobbers the values... 
        // no clean up necessary... 
    } 
    
  • +1

    私は 'new [] int(10)'が有効な新しい式であるとは思わない。あなたは '新しいint [10]'を意味しましたか? –

    +0

    @Charles:おそらく、私は血のこもった一日のうちに何かに答えようとしているのを嫌っています。ああ... ...--)私の頭はまったくありません。 –

    9

    C++関数から配列を返すことはできません。 8.3.5 [dcl.fct]/6:

    関数型配列または関数の戻り値の型を持っていてはならない[...]

    最も一般的に選ばれた選択肢は、の値を返すようにしていますそのクラスに配列が含まれるクラス型彼は(もしそうなら、彼はどのようにすべきである)の配列を解放する必要があるかどうか

    struct ArrayHolder 
    { 
        int array[10]; 
    }; 
    
    ArrayHolder test(); 
    

    または静的または動的に割り当てられた配列の最初の要素へのポインタを返すために、ドキュメントがユーザに示す必要が返されたポインタに指差す。

    など。

    int* test2() 
    { 
        return new int[10]; 
    } 
    
    int* test3() 
    { 
        static int array[10]; 
        return array; 
    } 
    

    配列への参照またはポインタを返すことが可能であるが、それは上記の方法のいずれかの上にない実用的な利点を有するより複雑な構文であるように、それは非常に稀です。

    int (&test4())[10] 
    { 
         static int array[10]; 
         return array; 
    } 
    
    int (*test5())[10] 
    { 
         static int array[10]; 
         return &array; 
    } 
    
    -1

    "はどのようにC++方法とどのようにそれを宣言しなければならないの配列を返すことができ INT []試験(ボイド);???"

    template <class X> 
        class Array 
    { 
        X  *m_data; 
        int m_size; 
    public: 
        // there constructor, destructor, some methods 
        int Get(X* &_null_pointer) 
        { 
         if(!_null_pointer) 
         { 
          _null_pointer = new X [m_size]; 
          memcpy(_null_pointer, m_data, m_size * sizeof(X)); 
          return m_size; 
         } 
         return 0; 
        } 
    }; 
    

    だけ

    class IntArray 
    { 
        int *m_data; 
        int m_size; 
    public: 
        // there constructor, destructor, some methods 
        int Get(int* &_null_pointer) 
        { 
         if(!_null_pointer) 
         { 
          _null_pointer = new int [m_size]; 
          memcpy(_null_pointer, m_data, m_size * sizeof(int)); 
          return m_size; 
         } 
         return 0; 
        } 
    }; 
    

    int型例えば

    Array<float> array; 
    float *n_data = NULL; 
    int  data_size; 
    if(data_size = array.Get(n_data)) 
    {  // work with array } 
    
    delete [] n_data; 
    

    例int型

    IntArray array; 
    int  *n_data = NULL; 
    int  data_size; 
    if(data_size = array.Get(n_data)) 
    { // work with array } 
    
    delete [] n_data; 
    
    関連する問題