2011-05-12 14 views
2

コードC++のポインタ配列

#include "stdafx.h" 
#include <iostream> 

void someFunc(double* pDoubleArray, int length) 
{ 
    double* pNewDoubleArray = new double[length]; 

    for(int i = 0; i < length; i++) 
    { 
     pNewDoubleArray[i] = i * 3 + 2; 
    } 

    pDoubleArray = pNewDoubleArray; 
} 
int main() 
{ 
    double dbls[] = { 1, 2, 3, 4, 5 }; 

    int length = sizeof dbls/sizeof dbls[0]; 

    std::cout << "Before..." << std::endl; 

    for(int i = 0; i < length; i++) 
    { 
     std::cout << dbls[i] << ", "; 
    } 

    std::cout << std::endl; 

    someFunc(dbls, length); 

    std::cout << "After..." << std::endl; 

    for(int i = 0; i < length; i++) 
    { 
     std::cout << dbls[i] << ", "; 
    } 

    std::cout << std::endl; 

    while(true){ } 

    return 0; 
} 

出力

Before... 
1, 2, 3, 4, 5, 
After... 
1, 2, 3, 4, 5, 

は、ここで私が何をしようとしていますものです: 1.配列を作成し、いくつかの値 2パスでそれを埋めます新しい配列を作成し、渡された配列を新しく作成された配列に再割り当てする関数へのポインタとしての配列 3.変更を印刷しますs

私はまだ変更が表示されていない、と私はなぜわからない。その結果、メモリリークの問題を無視

+5

ため息:

void someFunc(double*& pDoubleArray, int length) { double* pNewDoubleArray = new double[length]; for(int i = 0; i < length; i++) { pNewDoubleArray[i] = i * 3 + 2; } pDoubleArray = pNewDoubleArray; } 

あなたを呼び出す主な機能は、変更することができる値を渡す必要があります。もう一度、std :: vectorは本当に必要なものです。 –

+1

「ベクトル」を参照して渡さないと、同じ問題が発生します。 –

+0

既に持っているアレイを変更するのではなく、実際に新しいアレイを作成することを確認できますか?あなたの 'main'関数は元の配列を変更したいと思うようです。 –

答えて

1

関数someFuncのインターフェイスが間違っています。新しい配列のアドレスを返すためには、ポインタのアドレス(またはポインタへのポインタ)の参照が必要です。それ以外の場合は、単にローカル値を変更するだけです。

int main() 
{ 
    double dbls[] = { 1, 2, 3, 4, 5 }; 
    double* pArray = dbls; 
    // ... 

    someFunc(pArray, length); 
    // ... 

    for(int i = 0; i < length; i++) 
    { 
    std::cout << pArray[i] << ", "; 
    } 
    // ... 
} 
+0

ありがとうございます。好奇心から - 私はどのようにポインタにポインタを渡すのですか?私はしようとしました:void someFunc(double ** pDoubleArray、int length)、次にpDoubleArray =(double **)pNewDoubleArray;とsomeFunc((double **)pArray、length);しかし、これは変更が発生しないという私の元の問題をもたらしました。 –

+0

@Storm: '&'演算子を使って変数のアドレスを取得する必要があります: 'pArray = &dbls;'。しかし、新しく割り当てられたインスタンスへの参照を変更すると、古いデータへの参照が失われることがよくあります。古いデータが( 'new'キーワードを使用して)ヒープ上にも作成された場合、メモリが決して再利用されないことを意味します。 – Groo

+0

@Groo:私はしようとしました:double * pArray = &dbls;とエラーがありました: 'double(*)[5]'から 'double *'に変換できません –

0

+0

配列の名前は、ポインタのr値として使用できますが、ポインタのl値では使用できません。あなたの "修正"はコンパイルされません。 –

+0

@Ben Voigt、あなたはそれについて肯定的ですか?受け入れられた答えはそうでないと言われる。 :-) –

+0

はい、私は肯定的です。受け入れられた答えは実際のパラメータを変更しました、それはもはや 'dbls'ではありません。 –

0
void someFunc(double* & pDoubleArray, int length) 
// pass by reference ^^^ the pointer 

線pDoubleArray = pNewDoubleArray。ポインタ

どちらかのローカルコピーは、参照によってポインタを渡すことへのポインタを渡し、またはスタイルの問題だ新しい価値私の好みは、新しい値を返すようになり

、ビットを返し割り当てます。

+0

また、値を変更するだけで、新しい配列の割り当てや漏れを避けることができます。もちろん、 – rlc

0

古い配列をが使用しない関数に渡す理由は不明です

個々の値を変更している場合は、新しいアレイインスタンスを作成する必要はありません。そうでない場合は、新しい配列を作成して返します。だから、

、いずれかの元の配列に変更:

void someFunc(double* pDoubleArray, int length) 
{ 
    for(int i = 0; i < length; i++) 
    { 
     pDoubleArray[i] = i * 3 + 2; 
    } 
} 

または関数から新しい配列を返す:

// this indicates that the returned value is 
// actually a new instance 
double* getNewArray(double* pDoubleArray, int length) 
{ 
    double* pNewDoubleArray = new double[length]; 

    for(int i = 0; i < length; i++) 
    { 
     pNewDoubleArray[i] = i * 3 + 2; 
    } 

    return pNewDoubleArray; 
} 

を代替は、参照することによって、入力配列を渡すことですが、それは解放する複雑に未使用のインスタンス。

[編集]

この最後の場合明確にする:私は前にコメントしてきたよう

void someFunc(double** pDoubleArray, int length) 
{ 
    double* pNewDoubleArray = new double[length]; 

    for(int i = 0; i < length; i++) 
    { 
     pNewDoubleArray[i] = i * 3 + 2; 
    } 

    *pDoubleArray = pNewDoubleArray; 
} 

void main() 
{ 
    double dbls[] = { 1, 2, 3, 4, 5 }; 
    double* pArray = dbls; 

    // this will change what pArray 
    // points to 
    someFunc(&pArray, 5); 

    return 0; 
} 

を、ヒープへpArray点が前の配列を割り当てた場合、後者のアプローチは、メモリリークにつながりますsomeFuncを呼び出してください。