1

以下をコンパイルすると、最初の「cout」のみが正しく機能します。

void * functionname()
{
int i[3]={1,2,3};
int *p = i;
return p;
}

int main()
{

int *p = new int[3];
p= (int *)functionname();

std::cout<<p[1]<<"\n";
std::cout<<p[1]<<"\n";
std::cout<<p[2]<<"\n";
std::cout<<p[2]<<"\n";
std::cout<<p[3]<<"\n";
std::cout<<p[3]<<"\n";
delete [] p;
return 0;
}

何が問題なのか教えてください。

4

4 に答える 4

3

配列iは関数に対してローカルです。関数が戻ると終了し、ダングリング ポインターが残ります。を返すほうがよいstd::array

std::array<int, 3> functionname()
{
  return std::array<int, 3>{{1,2,3}};
}

このようにして、呼び出し元は配列のコピーを取得し、問題はありません。コピーのコストについて心配する前に、通常、コンパイラはコピーを除外するため、作成される配列は 1 つだけであることに注意してください。

基になるデータ ブロックにアクセスする必要がある場合は、theArray.data()またはを使用できます&theArray[0]。これらは、最初の要素へのポインターを提供します。

注 1 : C++11 をサポートしていない場合は、ヘッダーstd::tr1::arrayから使用できます。<tr1/array>それがない場合は、 を参照するboost::arrayか、独自の配列クラスを展開してください。

注 2 : サイズが実行時にしか分からない配列が必要な場合は、std::vector代わりに使用してください。

于 2013-11-15T07:01:46.417 に答える
2

に変更します

void * functionname() {
    int *i = new int[3];
    i[0] = 1;
    i[1] = 2;
    i[2] = 3;
    return i;
}

配列が関数の末尾を超えて存在する場合は、スタックではなくヒープに配置する必要があります。

@juanchopanza と @Servé が指摘しているように、正しいメモリ管理のために、完了したら必ずこれを破棄してください。

int *a = (int *)functionname();
//do something with a
delete[] a;
于 2013-11-15T07:04:17.327 に答える
0

以下に、ローカル配列を外部に取得するバージョンがあります。このバージョンは、あなたが持っているものに近いです。入力するフィールドへのポインターを渡しますfunctionname。コピーされた配列が利用可能なスペースに収まるようにする責任があります。

しかし、今では、オブジェクトのようなstd::vectorものを使用する方が良いです。新しいムーブ コンストラクター (c++11) を使用すると、さらに効率的になります。

また、インデックスへのアクセスが間違っていたことにも注意してください。C++ 配列は、1 ではなく 0 からインデックス付けされます。

#include <iostream>

void functionname(int* p)
{
    int i[3]={1,2,3};
    std::copy(i,i+sizeof(i)/sizeof(i[0]),p);
}

int main()
{

    int *p = new int[3];
    functionname(p);

    std::cout<<p[0]<<"\n";
    std::cout<<p[1]<<"\n";
    std::cout<<p[2]<<"\n";
    delete [] p;
    return 0;
}
于 2013-11-15T07:22:57.127 に答える