-6

次の再帰的多項式乗算を書きましたが、エラーが発生します。コードはこちら

#include<iostream>
#include<vector>
using namespace std;
#define N 4
float *mult(float p[],float q[],int n)
{
    float pl[N/2],ql[N/2],ph[N/2],qh[N/2];
    float t1[N/2],t2[N/2];
    float r[2*N-2],rl[N],rm[N],rh[N];
    int i,N2;
    if(N==1)
    {
        r[0]=p[0]*q[0]; return (float *)r;
            }
    for(i=0;i<N/2;i++)
    {
        pl[i]=p[i];
        ql[i]=q[i];
    }
    for(i=N/2;i<N;i++)
    {
        ph[i-N/2]=p[i];
        qh[i-N/2]=q[i];

    }
    for(i=0;i<N/2;i++) t1[i]=pl[i]*ph[i];
    for(i=0;i<N/2;i++) t2[i]=ql[i]*qh[i];
    rm=mult(t1,t2,N/2);
    rl=mult(pl,ql,N/2);
    rh=mult(ph,qh,N/2);
    for(i=0;i<N-1;i++) r[i]=rl[i];
    r[N-1]=0;
    for(i=0;i<N-1;i++) r[N+i]=rh[i];
    for(i=0;i<N-1;i++)
        r[N/2+i]+=rm[i]-(rl[i]+rh[i]);
    return (float *)r;
}

エラーはこれらです

(13): warning C4172: returning address of local variable or temporary
(28): error C2440: '=' : cannot convert from 'float *' to 'float [4]' There are no conversions to array types, although there are conversions to references or pointers to arrays
(29): error C2440: '=' : cannot convert from 'float *' to 'float [4]' There are no conversions to array types, although there are conversions to references or pointers to arrays
(30): error C2440: '=' : cannot convert from 'float *' to 'float [4]' There are no conversions to array types, although there are conversions to references or pointers to arrays
(36): warning C4172: returning address of local variable or temporary

私は理由が何であるか理解できませんでした?助けてください

4

3 に答える 3

2

警告 C4172: ローカル変数または一時のアドレスを返す

これは、特定のスコープを終了すると存在しなくなる変数のアドレスを返すため、未定義の動作を呼び出していることを意味します。これの 1 つの例を見ることができます。

float *mult(float p[],float q[],int n)

ローカル配列rを作成し、そのアドレスを返します。いつものように、他にもたくさんのエラーがありますが、これで終わります。

ベクトルを返すことで、この問題を回避できます。

std::vector<float> mult( .... ) { fill vector with values you would put in array and return it }

これは可能な解決策の 1 つにすぎません。ここでの利点は、メモリ管理について心配する必要がないことです。

于 2012-04-30T20:21:18.117 に答える
1

いくつかの異なる問題がありますが、それらは互いに関連しています。

最初と最後の警告はr、 が関数内のローカル変数であり、関数が戻ると消えてしまうためです。つまり、そのアドレスを返すことは、問題を引き起こしていることを意味します。呼び出し元は、もはや意味のあるものを指していないポインターを取得します。(ほとんどの場合、コードはまだ機能しますが、運が良かったからです。)

他のエラーは、配列へのポインターを返す関数があり、その戻り値を配列変数に割り当てようとしていることが原因です。(1)データの内容が配列にコピーされることを望んでいるのか、(2)配列変数が関数によって返されたデータの参照を開始することを望んでいるのかはわかりませんが、実際にはどちらも起こりません.

これらの問題の両方に対する解決策は同じです。配列とポインターの違い、および操作対象のデータが実際に存在する場所について、より明確に注意を払う必要があります。これを機能させるには、主に 3 つの方法があります。

vector<float>まず、データをC スタイルの配列ではなく、C++ のようなものに入れることができます。これらは、あなたがやろうとしているのとほぼ同じ方法で値によって渡すことができ、それはただうまくいくでしょう。ただし、大量のデータのコピーが必要になる場合があるため、コードが必要以上に遅くなる可能性があります。

第 2 に、C スタイルの raw ブロックのメモリを引き続き使用できますが、全体を通して配列の代わりにポインターを使用し、それらをnewand delete、またはmallocandを使用して明示的に割り当てfree、すべてが一度だけ解放されるように注意してください。

第 3 に、C スタイルの配列を引き続き使用することもできますが、関数から配列を返そうとする代わりに、配列の先頭へのポインターを関数に渡し、その新しい内容を埋めます。multそうすれば、メモリ管理は関数の呼び出し元の責任であり、正しく行えば、multそれ自体で何らかの種類のメモリ割り当てが必要になることをおそらく回避できます。(呼び出し元が何らかの一時スペースへのポインターを渡す必要があることに気付くかもしれません。再帰呼び出しは、適切に整理すれば、同じ一時スペースを使用できます。)

最初のアプローチは最も単純です。最後が最高のパフォーマンスかもしれません。真ん中はあまりお勧めしません。

于 2012-04-30T20:32:35.263 に答える
1

配列をr, rl, rm, rh動的にすると、警告とエラーの両方がなくなります。

#include <iostream>
#include <vector>
using namespace std;
#define N 4
float* mult(float p[],float q[],int n)
{
    float pl[N/2],ql[N/2],ph[N/2],qh[N/2];
    float t1[N/2],t2[N/2];
    float* r = new float[2*N-2]; // Create it dynamically so it can be safely returned
    float *rl, *rm, *rh; // They don't need to be allocated because they will be assigned later down there.
    int i,N2;
    if(N==1)
    {
        r[0]=p[0]*q[0];
        return r;
    }
    for(i=0;i<N/2;i++)
    {
        pl[i]=p[i];
        ql[i]=q[i];
    }
    for(i=N/2;i<N;i++)
    {
        ph[i-N/2]=p[i];
        qh[i-N/2]=q[i];

    }
    for(i=0;i<N/2;i++) t1[i]=pl[i]*ph[i];
    for(i=0;i<N/2;i++) t2[i]=ql[i]*qh[i];
    rm=mult(t1,t2,N/2);
    rl=mult(pl,ql,N/2);
    rh=mult(ph,qh,N/2);
    for(i=0;i<N-1;i++) r[i]=rl[i];
    r[N-1]=0;
    for(i=0;i<N-1;i++) r[N+i]=rh[i];
    for(i=0;i<N-1;i++)
        r[N/2+i]+=rm[i]-(rl[i]+rh[i]);
    return r;
}
于 2012-04-30T20:35:20.777 に答える