Con trỏ trong C # Unity


8

Này, tôi mới tìm hiểu về con trỏ gần đây và đang tự hỏi làm thế nào tôi có thể sử dụng chúng trong c # (tôi mới tìm hiểu về chúng trong c ++) trong sự thống nhất. Tôi có một số câu hỏi mặc dù.

  1. Con trỏ sử dụng lập trình cấp thấp để tìm vị trí của các giá trị khác nhau trên máy tính, điều đó có nghĩa là bạn chỉ có thể truy cập giá trị của biến từ bất kỳ tập lệnh nào?
  2. Nếu vậy làm thế nào để tôi chỉ gọi một vị trí của một biến chỉ bằng mã vị trí của nó?
  3. Có sự khác biệt rõ rệt nào giữa các con trỏ trong C # và C ++ mà tôi nên biết không?
  4. Làm cách nào tôi có thể sử dụng các con trỏ với các loại biến trong Unity (Vector3s, Transforms, GameObjects, v.v ...)?

Còn rất nhiều câu hỏi nữa mà tôi có lẽ nên và muốn hỏi nếu bạn có thêm thông tin hoặc nguồn nào.

Câu trả lời:


6

Nói chung cho C # và đặc biệt cho Unity tôi sẽ khuyên bạn nên chống lại nó ... nhưng nếu bạn thực sự muốn, hoặc có lý do chính đáng, bạn có thể.

Trong C #, bạn sẽ cần làm quen với cái được gọi là mã không an toàn . Đáng sợ?

Trong Unity, bạn sẽ cần bật chế độ biên dịch không an toàn để bạn không thể sử dụng trình phát web nếu bạn đã lên kế hoạch cho việc đó. Bạn có thể đọc thêm ở đây hoặc ở đây .

Vì vậy, về cơ bản C # được thiết kế với Garbage Collector như nhiều ngôn ngữ script. Ý tưởng chung là thử và trừu tượng hóa khái niệm quản lý bộ nhớ để đơn giản hóa sự phát triển. Bạn vẫn có thể bị rò rỉ tài nguyên nếu bạn không vô hiệu hóa các đối tượng của mình. Tôi thực sự không phải là một người ủng hộ rất lớn của các GC và thay vào đó sẽ thích các phương pháp RAII hơn , nhưng đây là thế giới chúng ta đang sống.

Tuy nhiên, hầu hết các nhà phát triển C ++ cũng đồng ý rằng dù sao bạn cũng không nên sử dụng con trỏ trực tiếp và nên sử dụng loại con trỏ thông minh được thiết kế RAII hay còn gọi là con trỏ thông minh . Nếu bạn ở vùng đất C thì con trỏ có khả năng là bản chất thứ hai đối với bạn, nhưng thậm chí sau đó nó giúp trừu tượng hóa chúng ở một mức độ nào đó.

Nếu bạn sử dụng chúng trong C #, hãy lưu ý rằng có một tiềm năng rất thực bạn có thể thêm các lỗ hổng bảo mật hoặc thực sự khó chịu và khó theo dõi các lỗi. Bạn cũng sẽ cần lưu ý rằng bạn phải cẩn thận không tham chiếu các đối tượng có thể được di chuyển bởi GC. Lưu ý việc sử dụng các tuyên bố cố định ở đây .

Bạn cũng có thể sử dụng Con trỏ trong Unity bằng cách viết một plugin gốc . Điều này một lần nữa sẽ loại trừ các bản dựng webplayer, nhưng tính năng HTML5 mới hoạt động dựa trên emscripten vì vậy nếu bạn có kế hoạch sử dụng mà bạn có thể có thể nếu bạn cẩn thận. Các plugin gốc cho phép bạn mở rộng Unity trên cơ sở từng nền tảng. Tôi đã viết một plugin gốc để giao tiếp với một số vi điều khiển thông qua kết nối nối tiếp chẳng hạn.

Vì vậy, để tóm tắt, bạn chắc chắn nên tự hỏi tại sao tôi muốn sử dụng con trỏ trong C # trong Unity. Nếu bạn chỉ muốn làm điều đó cho vui ... Hãy tự mình ra ngoài.

Chỉnh sửa: Tôi xin lỗi nếu tôi đã xúc phạm bất cứ ai vì tôi biết suy nghĩ của tôi về GC không phải là ý kiến ​​phổ biến ngay bây giờ.

Nếu bạn thực sự đọc câu trả lời của tôi, bạn sẽ lưu ý rằng tôi không gọi C # là ngôn ngữ kịch bản. Tôi so sánh nó với "nhiều ngôn ngữ kịch bản", tuy nhiên, trong ngữ cảnh của Unity, nó được sử dụng rất nhiều làm ngôn ngữ kịch bản. Nó là một phần của DSL to Unity nếu bạn muốn. Thường thì bạn sẽ thấy nó thậm chí còn được gọi là Unity Script trong ngữ cảnh này (phần lớn này liên quan đến thay thế Javascript của Unity cho C #). Nếu bạn đặt LLVM trong đường ống của mình, bạn có thể biên dịch nó thành mã riêng cho nền tảng ... vậy bạn sẽ gọi nó là gì? Vì vậy, thực sự tôi đã không muốn chia tóc ở đây.

Nhiều tài liệu tham khảo tuyệt vời về công nghệ phần mềm chứa đầy ý kiến:

Effective C ++ , hiệu quả hơn C ++ , C ++ Hỏi đáp , hiệu quả C # , hiện đại C ++ Thiết kế , Design Patterns ... Và không biết bao nhiêu người khác. Tôi không cảm thấy điều này làm cho các cuộc tranh luận trở nên ít đáng tin hơn nếu chúng được theo sau bởi lời giải thích chu đáo.

Tôi thực sự không nói "Đừng sử dụng con trỏ bao giờ !!" . Trong thực tế, tôi vẫn sử dụng chúng trần truồng. Tôi đã nói "nói chung" như trong "thích sử dụng mã an toàn hơn mã không an toàn trong C #". Có những tình huống có thể có lợi và đó là một trong những tính năng thực sự mạnh mẽ của C # để chọn và chọn công cụ của bạn. C # thậm chí cho phép bạn có sự minh bạch trong quy trình GC ở một mức độ nào đó, các ngôn ngữ như Dart không và có thể dẫn đến rò rỉ tài nguyên rất dễ dàng. Chắc chắn nếu bạn là nhà phát triển duy nhất của một dự án nhỏ thì đó không phải là vấn đề. Nếu bạn ở trong một nhóm nói 10+ với hàng trăm ngàn dòng mã thì nó có thể trở nên khó khăn.

Tôi chỉ đơn giản muốn người đọc thực hiện thận trọng khi sử dụng con trỏ trần. Đó là giống như nói rất cẩn thận khi làm việc với điện lưới. Tôi không nói đừng là thợ điện, chỉ là nếu bạn di chuyển sai và không đối xử với nó một cách tôn trọng thì bạn đã chết.

Tôi thích ví dụ được đưa ra bởi Lasse trong đó hiệu suất có thể đã đưa ra nhu cầu.


1
C # không phải là một ngôn ngữ kịch bản, nhưng nó có thể được sử dụng cho điều đó. Java cũng có một GC và nó cũng không phải là ngôn ngữ kịch bản. Trả lời với ý kiến ​​của riêng bạn những gì tốt nhất nói chung, không phải là câu trả lời khách quan mà chúng tôi đang tìm kiếm trên trang web này. Đối với một mục đích đặc biệt, một cái gì đó như mã không an toàn và con trỏ có thể thực sự hiệu quả.
Lasse

1
Tôi không hiểu tại sao câu trả lời này bị hạ thấp - nó rất nhiều thông tin và cho thấy rất nhiều nghiên cứu / kiến ​​thức và các liên kết để đọc thêm. Đặc biệt với @Lasse ngôn ngữ kịch bản gì? Tất nhiên sẽ chính xác hơn khi nói "ngôn ngữ được sử dụng để viết kịch bản thống nhất", nhưng tôi không thấy nhiều lý do để hạ thấp vì Matthew đã bỏ qua 7 từ rõ ràng và sử dụng một (một) thuật ngữ đơn giản hóa.
wonderra

@wondra Tôi không ủng hộ vì câu trả lời không làm rõ rằng có những nơi con trỏ rất có thể được sử dụng trong C #. Tất cả phụ thuộc vào mục đích và nền tảng mục tiêu. Trong thực tế, câu trả lời là cố gắng làm mọi người sợ hãi khi sử dụng con trỏ.
Lasse

1
@wondra Câu trả lời này hầu như không trả lời được câu hỏi. Tất cả những gì nó làm là nói không sử dụng con trỏ. Phần bình luận này không phải là nơi thích hợp để thảo luận về điều này. Bạn có thể tham gia trò chuyện nếu bạn nghĩ rằng bạn có nhiều tranh luận hơn.
Lasse

1
@Lasse không thể thuyết phục bạn và đó không phải là cuộc chiến của tôi, nhưng nhìn thấy câu trả lời của bạn - bạn đã viết chính xác như câu trả lời này (được đăng sớm hơn), hơn nữa bạn thậm chí chỉ bao gồm tập hợp con (= ít thông tin) về chủ đề như câu trả lời này đã làm.
wonderra

6

C # sử dụng các tham chiếu để truyền xung quanh các đối tượng không phải là loại giá trị . Điều này có nghĩa là mọi thứ thường được thông qua tham chiếu. Nếu bạn muốn chuyển loại giá trị theo tham chiếu, bạn có thể sử dụng từ khóa ref . Sự khác biệt của loại tham chiếu và loại giá trị là tùy thuộc vào loại giá trị lớn như thế nào, nó thường đòi hỏi nhiều bộ nhớ được sao chép khi truyền vào hàm. Một tham chiếu chỉ là 32 bit hoặc 64 bit , hoặc 4 byte hoặc 8 byte. Bạn có thể nhận được nhiều hiệu suất hơn từ mã của mình trong các vòng lặp rất chặt chẽ nếu bạn sử dụng các tham chiếu thay vì chỉ sao chép tất cả dữ liệu mà các biến được nhập giá trị chứa, giả sử chúng lớn hơn 4 hoặc 8 byte.

Ví dụ: trên Unity bất kỳ đối tượng MonoBehaviour (lớp) nào là kiểu tham chiếu và bất kỳ đối tượng Vector3 (struct) nào cũng là loại Giá trị.

Ngoài ra còn có các khối mã không an toàn sẽ cho phép bạn nhập mã cho phép bạn tạo và sửa đổi dữ liệu một cách không an toàn. Để sử dụng mã không an toàn, bạn sẽ phải đặt trình biên dịch để cho phép mã không an toàn. Con trỏ có thể được sử dụng theo cách này. Bằng cách sử dụng mã không an toàn, một số kiểm tra không được sử dụng có mã an toàn, điều này làm cho mã không an toàn khó viết hơn. Có rất ít nơi có thể hưởng lợi từ mã không an toàn trên C #. Trên Unity mã không an toàn không được hỗ trợ trên tất cả các nền tảng. Thông thường sử dụng tài liệu tham khảo thay vì con trỏ không an toàn là đủ khi làm việc với Unity.

Dưới đây là một ví dụ ( nguồn ) về việc sử dụng các con trỏ mã không an toàn trong C # với Unity:

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);
            }
        }
    }
}

Tôi thấy thú vị khi bạn chỉ trích câu trả lời của tôi và sử dụng cùng các đối số, trừ thông tin liên quan khác và chỉ bao gồm một cuộc thảo luận ngắn gọn về giá trị so với các loại tham chiếu. Ít nhất bạn có thể đề cập đến Boxing , tối ưu hóa JIT đôi khi có thể loại bỏ chi phí sao chép loại giá trị, làm thế nào để tránh mất an toàn bằng cách sắp xếp theo thứ tự , hoặc có lẽ mã không an toàn không phải lúc nào cũng nhanh hơn an toàn
Matthew Sanders

Tôi xin lỗi nếu bạn cảm thấy bị tấn công hoặc bị xúc phạm. Đo không phải y định của tôi. Tôi chỉ trích câu trả lời của bạn cho rằng dường như tôi rất dựa trên quan điểm thay vì dựa trên thực tế. Tôi đã cung cấp anwers cho các câu hỏi được hỏi cùng với một số mã ví dụ. Từ câu trả lời của bạn, tôi không thể hiểu những điều tôi đã giải thích trong câu trả lời của mình, điều mà tôi cảm thấy có liên quan hơn đến câu hỏi được hỏi. Tôi không thấy GC có liên quan gì đến "làm thế nào để tôi sử dụng con trỏ?" hoặc tôi không thấy bạn đề cập đến cách các tài liệu tham khảo hoạt động trên C # vì câu hỏi dường như giả sử các biến hoạt động theo cùng một cách trong C # và C ++.
Lasse

1
Đừng lo lắng. Cảm ơn lời xin lỗi của bạn. Tôi đã đề cập đến GC vì bạn cần lưu ý rằng việc chuyển con trỏ đến các loại được quản lý có thể gây ra vấn đề nếu GC đột nhiên di chuyển đối tượng. Tôi đã giả định rằng người đọc đã biết về hệ thống loại C # và cách sử dụng loại tham chiếu so với các loại giá trị.
Matthew Sanders

Các bạn thực sự làm cho nó khó khăn để chấp nhận một câu trả lời. Cả hai bạn đều cung cấp cho tôi nhiều thông tin cần thiết vì vậy tôi sẽ bỏ phiếu cho cả hai bạn và sẽ chấp nhận thông tin nào được đưa ra trước. Tôi không có ý gì với nó. Tôi chỉ có một thời gian khó khăn để lựa chọn và vì sợ tôi từ "mã không an toàn" đừng lo lắng. Tôi chưa bao giờ là người lùi bước trước một thử thách. Mặc dù bây giờ tôi biết rằng làm việc với các con trỏ là không thực tế vì nó liên quan đến phát triển đa nền tảng. Tôi muốn cảm ơn tất cả các bạn đã dành thời gian và ý kiến ​​của bạn. và tôi xin lỗi tôi đã bắt đầu WWIII không muốn làm điều đó.
Ryan Henry
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.