
A 回答 (8件)
- 最新から表示
- 回答順に表示

No.8
- 回答日時:
もうひとつ
まず、CやC++の世界では、
関数の引数として配列を渡すような
表記は、単に、ポインタを渡してい
るだけなので、引数として指定した
場合には、受け渡しだけでは、要素
毎のコピーは発生しません。
たとえば、
http://www.kouno.jp/home/c_faq/c6.html#4
にある、「 なぜなら配列が渡された
ときに、関数が実際に受け取るのはポ
インター であるからである」
さて、それだけではなんなので、
単純にポインタを引数とせずに配列
を渡す形にした方がわかりやすい例
です。
関数の引数に配列表現を使うのは、
多次元(実際には配列の配列)を
使うときにわかりやすくなるという
効果があります。
たとえば
int color[1024][768];
というような配列を渡したいとき、
ポインタとしてやりくりするより、
シンプルに
void revers(int color[1024][768]);
のように渡して、関数内で配列として
取り扱う方がわかりやすいと思います。
ただ、厳密に言えば、
・Cには多次元配列はない
(あるのは、配列の配列の……)
・関数の引数で書いた配列の
要素数は無視される
というのがあって、一番内側の
数字は無視されます。
ですので、
void revers(int color[][768]);
でも同じです。
ただし、
void revers(int color[][]);
void revers(int color[1024][]);
はエラーになります。
また、たとえ、
void revers(int color[1024][768]);
と書いても、実際の配列の要素数は
チェックされませんので、注意が必要
です。
多次元配列はないという意味は、実は
int color[1024][768];
は、
・int [768] という配列の型があって
・それが、[1024] 個ある配列
という意味になります。
ですから、
void revers(int color[][768]);
の内側の [] は、配列の要素数なので
無視される(なくても良い)
外側の [678] は、int [768] という
型の一部なので、省略不可
ということになります。
No.7
- 回答日時:
初心者とのことなので、理解できる可能性は低いですが...
結果を格納する配列を引数として渡す場合、一般的には強い例外安全保障ができなくなります。配列の要素のコピーコンストラクタが決して失敗しないか、決して失敗しないswapが用意されている場合だけ、強い例外安全保障が可能になります。その場合でも、正しく実装するには相応の知識が必要です。
具体的には、
void func(std::string array[10])
{
std::string temp[10] = { ... };
for (int i = 0; i < 10; i++)
array[i].swap(temp[i]);
}
のようにしなければなりません。
つまり、関数内部で一通りのコピーが必ず発生します。

No.6
- 回答日時:
再度補足です。
引数で配列を受け渡しする方法がわかりに
くいので。
関数の仮引数の形で、配列を指定する
表現方法があります。
void func(int a[]);
のようにすれば、この引数は、int の
配列であることを明示できます。
具体的な処理としても
void func(int a[])
{
int x = a[10];
// 呼び出したり、
a[11] = x + 1;
// 代入したり
}
できます。
このとき、引数を経由した操作は、
呼び出し側に反映されます(後述)
また、配列のサイズは直接渡されま
せんので、上記の場合、a[10] や、
a[11] が存在しなくてもコンパイラは
何も言いません。
(実行時に良くないことが起こるで
しょう)
この関数を呼び出すときには、配列名を
引数にできます。
main()
{
int x[100];
func(x);
のように
}
ただ、この場合は、本当は、配列を
引き渡しているのではなく、配列の
先頭を指すポインタを渡しているだ
けです。
ですので、
void func(int a[]);
は、
void func(int *a);
と同じだと考えて差し支えありません。
実際には、このように、アドレスを
渡しているので、関数側の操作が
呼び出し側に反映されてしまうわけで
す。

No.5
- 回答日時:
補足です。
ANSI 以降のCでは、「構造体を返す」のは、
値をコピーするので処理コストがかかるとい
う以上の問題はありません。
処理スピードを問題にしなければ、返せる
値のサイズにも上限はありません。
「構造体を返す」場合は、単に、値のコピー
が発生するだけですから、メモリをどう確保
するかは、処理系にお任せすれば良いことに
なっています。
ただ、普通は、関数の返値として返すのでは
なく、引数として渡すことが多いですね。
int a[100];
に対して、
void func(a[])
{ ..... }
という関数に、
func(a);
と渡せば、関数内で、配列 a を操作できます。
あえて、(構造体経由で)配列を「返す」なら
たとえば、
a.h
-------
struct array_type
{
int a[1024];
};
array_type func(int v);
-------
a.cpp
------
#include "a.h"
array_type func(int v)
{
array_type wk;
for (int i = 0; i < 1024: i++)
wk.a[i] = v;
return wk;
}
------
b.cpp
------
#include "a.h"
int main()
{
arrya_type value;
value = func(3.14);
// ここで、値のコピーが発生する
// いろいろな処理
// value.a[i] などで、配列としては機能する
// でも、本当は、構造体
}
------
これで、あえて、メモリを明示的に確保すること
も、メモリリークを起こすこともなく、実行は
できます。
ただ、後で読む人が、「なぜここで構造体?」
と悩むことにはなると思います。
C++では、(明示的に定義してあれば)コピー
コンストラクタというのがあって、これが悪さを
するとか、これがないために、「単なる値のコピー」
が発生するとか、そういう話題はありますが、
普通に構造体を返すのは、上述のような、大きな
データのコピーという問題があるだけです。
No.4
- 回答日時:
ネイティブコードはプリミティブな値(Max64ビット)しか返せません。
オブジェクト型を返す場合でも関数からの戻り値はポインタで、本体は
別のメモリ空間にあります。
そもそも、C言語では配列の次元、要素数の管理は利用者の責任で
行うことになっています。つまり、「配列の先頭だけ渡すから、あとは
勝手にやってくれ」なのです。故に、要素数を5個しか定義していない
配列に対し、インデックスが6でアクセスしてもエラーになりません。
個人的な意見ですが、C、C++で配列や構造体を戻り値の型にするのは
プログラムの効率的な作り方から見れば、「やってはいけない」の
代表格みたいなものです。
先ず、次のことを考えてみてください。
★呼び出されたメソッドが返す配列は何処に作られたものか?
自動変数であれば、メソッドから返った時に解放されてしまい、
内容は不定になります。また、メソッド内でアロケートしたもの
であるなら、メモリを解放する責任は誰にあるのか?
★それでも、明示的にアロケートしているなら百歩譲って良しと
しましょう。しかし、単に構造体なりを返すと、先に述べたように
戻り値を保存しておくメモリを確保する内部コードが生成される
ことがあります。(実際にそうなるケースが多い)
すると、ソースコード上では見えないメモリを消費しますし、誰も
解放しないので、繰り返し実行するとメモリストレスになります。
よって、配列や構造体を返す場合は呼び出し側が領域を確保して、
そのポインタを渡し、呼び出されたメソッドはそこに結果を記録
するべきだと思います。
この回答への補足
C++を学び始めて1ヶ月もたっていないのでよく分かりません。
やりたいことはa.cppとb.cppでbで作った配列をaで受け取れるようにしたいのですがどのようにしていいか分からず困っています。
よろしくお願いします。

No.3
- 回答日時:
配列全体を直接返す方法はありません。
ただ、構造体は直接返すことができます。
これを応用すると、配列をメンバーにし
た構造体を返すことで、実質的に配列を
返すという手もあります。
同じく、配列は直接代入できないのでが、
構造体は直接代入できるので、配列をメ
ンバーとする構造体経由で、配列を代入
したりもできます。
No.2
- 回答日時:
通常は ポインタを渡すしかないんじゃないのかな
古い考えなら呼び元で領域確保して処理側へ確保できたポインタを渡して終ったら確保された値を順に使う・・・
今は色々やり方は有るだろうけど大きくは変ってない筈・・・
No.1
- 回答日時:
配列を直接返す方法はありません。
お勧めなのは、
std::auto_ptr< std::vector<int> > func();
のように、vectorをauto_ptrにして返す方法です。
auto_ptrにしておかないとvector全体のコピーが発生するため、効率が低下するとともに、例外が送出するリスクも発生します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) 配列操作について 5 2023/04/18 07:27
- Microsoft ASP プログラミング関係で質問です。 3 2022/10/11 16:06
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- Visual Basic(VBA) Vbaで数式をポーランド記法に変換するコードを作って実行しようとするとフリーズします。 1 2022/05/24 17:53
- Excel(エクセル) ExcelVBAでリストの項目に必要数と同じ手配数を分配していくマクロを作りたいです。 1 2022/07/29 18:36
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- その他(プログラミング・Web制作) PythonでLoopを使って配列内の文字列を結合する。そして [] を削除する 1 2022/03/31 23:28
- Visual Basic(VBA) 列を指定して文字を切り出し、他の列と結合 5 2022/09/03 08:23
- C言語・C++・C# 至急教えてください! プログラミングの問題です! お願いします! 出力2と全く同じ出力をするように、 2 2022/06/22 23:10
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
複数の選択範囲の行番号を個別...
-
キーボード配列をもとに戻す方法
-
先頭アドレスとは何ですか?
-
配列を含む構造体の初期値について
-
C言語初心者 ポインタについて...
-
配列で格納したものをmsgboxで...
-
配列の大きさを決めない状態で...
-
C# 配列の変数宣言について。
-
C言語で特定列だけを抽出して配...
-
9枚の写真がA4 1枚に印刷できま...
-
多次元配列を分かりやすく教え...
-
現在、C/C++ で作成したプログ...
-
Dimとは・・・
-
配列と他の変数のメモリ領域重...
-
ASUSのノートパソコンは使いや...
-
C言語のオーバーフローについて
-
ポインタの配列のコンマについて
-
テキストファイルから文字列を...
-
ヘッダーファイルからの取り込...
-
ExcelVBAで質問です。離れた二...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
C# Listを使わずに2次元配列の...
-
【速いブラインドタッチ】手を...
-
配列をEraseしてもメモリが開放...
-
テキストファイルから文字列を...
-
先頭アドレスとは何ですか?
-
配列で格納したものをmsgboxで...
-
複数の選択範囲の行番号を個別...
-
C# 配列の変数宣言について。
-
C++ vectorに配列をプッシュしたい
-
配列を含む構造体の初期値について
-
VBで構造体の配列を関数に渡す...
-
C言語で特定列だけを抽出して配...
-
キーボードのキー配列について
-
ExcelVBAで質問です。離れた二...
-
2次元配列を戻り値とする関数?
-
unsigned char配列への入力の仕方
-
【C言語】配列の中に配列を入れ...
-
Redimした動的配列はEraseする...
おすすめ情報