doubingjiu3199 2016-01-25 20:00
浏览 10
已采纳

在设计方面和编写库时,什么时候应该使用指针作为参数,什么时候不应该使用指针?

Sorry if my question seems stupid. My background is in PHP, Ruby, Python, Lua and similar languages, and I have no understanding of pointers in real-life scenarios.

From what I've read on the Internet and what I've got as responses in a question I asked (When is a pointer idiomatic?), I have understood that:

  • Pointers should be used when copying large data. Instead of getting the whole object hierarchy, receive its address and access it.
  • Pointers have to be used when you have a function on a struct that modifies it.

So, pointers seem like a great thing: I should just always get them as function arguments because they are so lightweight, and it's okay if I somehow end up not needing to modify anything on the struct.

However, looking at that statement intuitively, I can feel that it sounds very creepy, and yet I don't know why.

So, as someone who is designing a struct and its related functions, or just functions, when should I receive a pointer? When should I receive a value, and why?

In other words, when should my NewAuthor method return &Author{ ... }, and when should it return Author{ ... }? When should my function get a pointer to an author as an argument, and when should it just get the value (a copy) of type Author?

  • 写回答

2条回答 默认 最新

  • dtjzpg5313 2016-01-25 21:28
    关注

    There's tradeoffs for both pointers and values.

    Generally speaking, pointers will point to some other region of memory in the system. Be it the stack of the function that wants to pass a pointer to a local variable or some place on the heap.

    func A() {
        i := 25
        B(&i) // A sets up stack frame to call B,
              // it copies the address of i so B can look it up later.
        // At this point, i is equal to 30
    }
    func B(i *int){
         // Here, i points to A's stack frame.
         // For this to execute, I look at my variable "i", 
         //   see the memory address it points to, then look at that to get the value of 25.
         // That address may be on another page of memory, 
         // causing me to have to look it up from main memory (which is slow).
         println(10 + (*i)) 
    
         // Since I have the address to A's local variable, I can modify it.
         *i = 30
    }
    

    Pointers require me to de-reference them constantly whenever I was to see the data it points to. Sometimes you don't care. Other times it matters a lot. It really depends on the application.

    If that pointer has to be de-referenced a lot (ie: you pass in a number to use in a bunch of different calcs), then you keep paying the cost.

    Compared to using values:

    func A() {
        i := 25
        B(i) // A sets up the stack frame to call B, copying in the value 25
        // i is still 25, because A gave B a copy of the value, and not the address.
    }
    func B(i int){
         // Here, i is simply on the stack.  I don't have to do anything to use it.
         println(10 + i) 
    
         // Since i here is a value on B's stack, modifications are not visible outside B's scpe
         i = 30
    }
    

    Since there's nothing to dereference, it's basically free to use the local variable.

    The down side of passing values happens if those values are large because copying data to the stack isn't free.

    For an int it's a wash because pointers are "int" sized. For a struct, or an array, you are copying all the data.

    Also, large objects on the stack can make the stack extra big. Go handles this well with stack re-allocation, but in high performance scenarios, it may be too much of an impact to performance.

    There's a data safety aspect as well (can't modify something I pass by value), but I don't feel that is usually an issue in most code bases.

    Basically, if your problem was already solvable by ruby, python or other language without value types, then these performance nuances don't super-matter.

    In general, passing structs as pointers will usually do "the right thing" while learning the language.

    For all other types, or things that you want to keep as read-only, pass values.

    There are exceptions to that rule, but it's best that you learn those as needs arise rather than try to redefine your world all at once. If that makes sense.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 要这个数学建模编程的代码 并且能完整允许出来结果 完整的过程和数据的结果
  • ¥15 html5+css和javascript有人可以帮吗?图片要怎么插入代码里面啊
  • ¥30 Unity接入微信SDK 无法开启摄像头
  • ¥20 有偿 写代码 要用特定的软件anaconda 里的jvpyter 用python3写
  • ¥20 cad图纸,chx-3六轴码垛机器人
  • ¥15 移动摄像头专网需要解vlan
  • ¥20 access多表提取相同字段数据并合并
  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角
  • ¥20 Java-Oj-桌布的计算
  • ¥15 powerbuilder中的datawindow数据整合到新的DataWindow