C#Unityのポインター


8

ちょっと最近ポインタについて学んだばかりで、c#でそれらをどのように使用できるのか疑問に思っています(c ++でそれらについて学んだばかりです)。でもいくつか質問があります。

  1. ポインターは低レベルのプログラミングを使用してコンピューター上のさまざまな値の位置を見つけます。つまり、任意のスクリプトから変数の値にアクセスできるということですか。
  2. もしそうなら、ロケーションコードだけで変数のロケーションを呼び出すにはどうすればよいですか?
  3. C#とC ++のポインターの間に、私が知っておくべき識別可能な違いはありますか?
  4. Unityの変数タイプ(Vector3s、Transforms、GameObjectsなど)でポインターを使用するにはどうすればよいですか?

さらに多くの質問があるので、追加の情報やソースがあるかどうかを確認します。

回答:


6

一般的にはC#について、特にUnityについてはお勧めしません。

C#では、「安全でないコード」と呼ばれるものに慣れる必要があります。まだ怖い?

Unityでは、安全でないコンパイルモードを有効にする必要があります。そうすることで、予定どおりにWebプレーヤーを使用できなくなります。詳しくはこちらまたはこちらをご覧ください

したがって、基本的にC#は、多くのスクリプト言語と同様にガベージコレクターで設計されました。一般的な考え方は、メモリ管理の概念を試して抽象化し、開発を簡素化することです。オブジェクトを無効にしないと、リソースリークが発生する可能性があります。私は正直なところ、GCの大規模な支持者ではないため、代わりにRAIIメソッドを使用しますが、これは私たちが住んでいる世界です。

ただし、ほとんどのC ++開発者は、ポインタを直接使用するのではなく、RAIIで設計された型(スマートポインタ)を使用することを推奨することにも同意します。Cランドにいる場合、ポインタは2番目の性質ですが、それでもある程度抽象化するのに役立ちます。

C#でそれらを使用する場合は、セキュリティの脆弱性を追加したり、非常に厄介でバグを追跡するのが非常に難しい可能性があることに注意してください。また、GCによって移動できるオブジェクトを参照しないように注意する必要があることにも留意する必要があります。ここでは、fixedステートメントの使用に注意してください

Unityでポインターを使用するには、ネイティブプラグインを記述します。これもまた、Webplayerビルドを除外しますが、新しいHTML5機能はemscriptenに基づいて機能するため、使用を計画している場合は、慎重に使用することができます。ネイティブプラグインを使用すると、プラットフォームごとにUnityを拡張できます。たとえばシリアル接続を介して一部のマイクロコントローラーと通信するためのネイティブプラグインを作成しました。

まとめると、UnityのC#でポインターを使用する理由を自問する必要があります。ただ楽しみたいだけなら...ノックアウトしてください。

編集: GCについての私の考えが今のところ一般的な意見ではないことを知っているので、誰かを気分を害したのは残念です。

本当に私の答えを読んだら、私はC#をスクリプト言語と呼んでいないことに気付くでしょう。「多くのスクリプト言語」と比較しますが、Unityのコンテキストでは、スクリプト言語として非常に使用されています。Unity にとっては、DSLのようなものです。多くの場合、このコンテキストではUnityスクリプトと呼ばれることもあります(これは主に、UnityのC#に代わるJavaScriptを参照しています)。パイプラインにLLVMを配置する場合、プラットフォーム用のネイティブコードに直接コンパイルできます。それを何と呼びますか?だから私はここで髪を分割したくありませんでした。

ソフトウェア工学への多くの素晴らしい参照は意見で満たされます:

効果的なC ++より効果的なC ++C ++ FAQ効果的なC#最新のC ++デザインデザインパターン ... 考え抜かれた説明が続いた場合、これが議論の信頼性を低下させるとは思わない。

私はすべてと言って外に本当にありませんでした「DOは、これまでのポインタを使用しないで!!」。実際、私は時々それらを裸で使用します。「C#では安全でないコードよりも安全なコードを使用することをお勧めします」のように「一般的に」と言いました。それが有益である状況があり、それはツールを選択するC#の本当に強力な機能の1つです。C#では、GCプロセスにある程度の透過性を持たせることもできますが、Dartのような言語では、透過性がなく、リソースリークを非常に簡単に引き起こす可能性があります。あなたが小さなプロジェクトの唯一の開発者であるなら、それはおそらく問題ではありません。数十万行のコードを持つ10以上のチームにいる場合は、トリッキーになる可能性があります。

私は単に、裸のポインターを使用するときに読者に注意を払ってほしかった。主電源で作業する場合は、非常に注意が必要であると言えます。電気技師にならないと言っているのではありません。もしあなたが間違った動きをし、あなたが死んでいるという点でそれを扱わない場合に限ります。

私は、パフォーマンスが必要性を決定したかもしれないラッセによって与えられた例が好きです。


1
C#はスクリプト言語ではありませんが、そのために使用できます。JavaにもGCがあり、それもスクリプト言語ではありません。一般的に何が最善かを自分の意見で答えることは、このサイトで私たちが探している客観的な答えではありません。特別な目的では、安全でないコードやポインタのようなものが本当に効率的です。
Lasse

1
私はなぜこの回答が反対票を投じられたのか理解していません-それは非常に有益であり、多くの研究/知識とさらなる読書へのリンクを示しています。特に@Lasseにとってスクリプト言語とは何ですか?もちろん、「統一のスクリプトに使用される言語」と言う方がより正確ですが、マシューが7つの明白な単語を省略し、1つの(過度に)簡略化した用語を使用したため、反対投票する理由はあまりありません。
2015年

@wondra回答は、C#でポインターを非常にうまく使用できる場所があることを明確にしていないため、私は投票しませんでした。それはすべて目的とターゲットプラットフォームに依存します。実際、答えは、ポインタを使用することからすべての人を怖がらせることです。
Lasse

1
@wondraこの答えは質問にほとんど答えていません。ポインタを使用しないように指示するだけです。このコメントセクションは、これを議論する適切な場所ではありません。議論があると思われる場合は、チャットに参加できます。
Lasse

1
@Lasseはあなたとその私の戦いを納得させることはできませんが、あなたの答えを見てください-あなたはこの答えと同じように(より早く投稿されました)書いただけでなく、この答えがそうであったように、トピックにサブセットのみ(=情報が少ない)も含めました。
2015年

6

C#は、参照を使用して、値型ではないオブジェクトを渡します。これは、すべてが通常参照によって渡されることを意味します。値型を参照渡しする場合は、refキーワードを使用できます。参照型と値型の違いは、値型の大きさに応じて、通常、関数に渡されるときにコピーするメモリが多く必要になることです。参照は、32ビットまたは64ビット、または4バイトまたは8バイトです。値型変数に含まれるすべてのデータをコピーする代わりに参照を使用すると、コードが非常にタイトなループでコードからより多くのパフォーマンスを引き出すことができます。

たとえば、Unityでは、MonoBehaviour(クラス)オブジェクトは参照タイプであり、Vector3(構造体)オブジェクトは値タイプです。

安全でないコードブロックもあり、データを安全に作成および変更できるコードを入力できます。安全でないコードを使用するには、安全でないコードを許可するようにコンパイラを設定する必要があります。ポインターはこの方法で使用できます。安全でないコードを使用することにより、安全なコードに存在する特定のチェックが使用されないため、安全でないコードをエラーなしで作成することが困難になります。C#の安全でないコードの恩恵を受けることができる場所ほとんどありません。Unityでは、安全でないコードがすべてのプラットフォームでサポートされているわけではありません。通常、安全でないポインタの代わりに参照を使用すると、Unityで作業するときに十分です。

UnityでC#の安全でないコードポインターを使用する例(ソース)は次のとおりです。

public static class Rope
{
    // C# function declaration to match C++
    [DllImport(SlingshotImport.c_libName)]
    static unsafe extern void UpdateRopeParticlesUnsafe(
        Vector3* oldNew,
        Vector3* curr,
        int numParticles);

    // C# wrapper function for Unity C# script
    static void UpdateRopeParticles(
        Vector3[] oldNew,
        Vector3[] curr,
        int numParticles)
    {
        unsafe
        {
            fixed (Vector3* oldNewPtr = oldNew)
            fixed (Vector3* currPtr = curr)
            {
                UpdateRopeParticlesUnsafe(oldNewPtr, currPtr, numParticles);
            }
        }
    }
}

私の答えを批判し、他の関連情報を除いて同じ引数を使用し、値と参照型の簡単な説明のみを含めるのは興味深いことです。少なくとも、ボクシング、値型コピーのオーバーヘッドを取り除くことができるJIT最適化、マーシャリングによって危険を回避する方法、または危険なコードが常に安全であるとは限りません
Matthew Sanders

攻撃を受けたり気分を害したりして申し訳ありません。それは私の意図ではありませんでした。事実に基づくのではなく、非常に意見に基づいているように思われたので、私はあなたの答えを批判しました。いくつかのサンプルコードと一緒に、質問の答えを用意しました。あなたの答えから、私が答えで説明したことを理解することができませんでした。それは、尋ねられた質問により関連していると感じました。GCが「ポインタの使用方法」とどのように関係しているかはわかりません。または、C#とC ++で変数が同じように機能することを質問が想定しているように思われたため、C#で参照が機能する方法について言及していませんでした。
Lasse

1
心配ない。お詫び申し上げます。マネージ型にポインターを渡すと、GCが突然オブジェクトを移動した場合に問題が発生する可能性があることに注意する必要があるため、GCについて説明しました。私は、読者がC#の型システムと、参照型と値型の使用方法を知っていると思いました。
Matthew Sanders、

皆さんは本当に答えを受け入れるのを難しくしています。あなたは両方とも私に必要な多くの情報を提供したので、私はあなたの両方に賛成票を投じ、最初に来たものを受け入れるつもりです。何の意味もありません。私は選ぶのに苦労しているだけで、「安全でないコード」から私を怖がらせることについては心配しないでください。とにかく挑戦から後退したことは一度もありません。しかし、ポインターの操作はマルチプラットフォーム開発に関係するため、実用的でないことはわかっています。お時間とご意見をありがとうございました。申し訳ありませんが、私は第二次世界大戦を開始しましたが、それを行うつもりはありませんでした。
ライアンヘンリー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.