【问题标题】:Passing pointers to function without copying it将指针传递给函数而不复制它
【发布时间】:2014-01-23 12:52:53
【问题描述】:

如何在程序中传递数据而不是每次都复制?

具体来说,在调用sim(ohlc)时我只想传递指针引用,不想将数据复制到函数中。

这是我制作的程序,但我不确定这是最好的方法(特别是在速度和内存使用方面)。

我认为我没有像我应该的那样将指针传递给sim(ohlc),但是如果我尝试sim(&ohlc),我不知道如何更改sim 函数来接受它。

   struct ohlcS {
        vector<unsigned int> timestamp;
        vector<float> open;
        vector<float> high;
        vector<float> low;
        vector<float> close;
        vector<float> volume;
    } ;


ohlcS *read_csv(string file_name) {
    // open file and read stuff
    if (read_error)
        return NULL;
    static ohlcS ohlc;
    ohlc.timestamp.push_back(read_value);
    return &ohlc;
}

int sim(ohlcS* ohlc) {
    // do stuff
    return 1;
}


main() {
    ohlcS *ohlc = read_csv(input_file);
    results = sim(ohlc);
}

【问题讨论】:

  • 您传递给sim()-函数的正是一个指针。
  • 当您将指针传递给sim() 时,您不会复制数据。只是指针。
  • 只是一个建议,不要使用类名作为变量名 ohlc *ohlc 很混乱。
  • @VictorPolevoy 那么,这是正确的做法吗?
  • @EricFortin 好的,我会改变它。

标签: c++ pointers stl


【解决方案1】:

它是 C++,使用参考。这是安全的,因为您返回一个静态对象。

static ohlc ohlc_not_found;

ohlc &read_csv(string file_name) {
    // open file and read stuff
    if(error_while_opening)
    {
        return ohlc_not_found;
    }
    static ohlc loc_ohlc;
    loc_ohlc.timestamp.push_back(read_value);
    return loc_ohlc;
}

int sim(const ohlc& par_ohlc) {
    // do stuff
    return 1;
}

....
 ohlc& var_ohlc = read_csv(input_file);
 if(var_ohlc == ohlc_not_found)
 {
      // error handling
      return;
 }
 results = sim(var_ohlc);

如果要修改sim中的par_ohlc,请不要设为const。

并且不建议将ohlc 用于类名和变量名:(

【讨论】:

  • 但是我怎样才能以这种方式从 read_csv 返回 NULL?如果我无法读取文件?
  • 你可以传入一个额外的参数(例如int&amp; error_indicator)来告诉用户是否有错误。指针的问题是人脑会自动尝试释放它们:) 或者您可以声明一个全局静态空 ohlc (ohlc_not_found) 变量,并将返回值设置为以防出错。
  • 你可以抛出std::invalid_argument异常。
  • 这不起作用,它说:error: invalid operands to binary expression ('ohlc' and 'ohlc') 我认为这是因为 ohlc 没有实现 ==?
  • @walle IO 异常不是无效参数,这里最好使用特定的 IO 异常。
【解决方案2】:

排队:

results = sim(ohlc);

您将 ohlc 指针传递给 sim 函数,没有进行深度数据复制,仅复制 32 位指针值。

【讨论】:

    【解决方案3】:

    这会将地址(32 位值)压入堆栈。

    results = sim(ohlc);
    

    喜欢:

      ; ...
      push eax ; addr of struct/class/whatever
      call function ; jump to function
    
      ; ...
    
    function:
      push ebp
      mov ebp, esp
      mov eax, [ebp+8] ; ebp+8 is the 32 bit value you pushed before onto the stack
                       ; -> your pointer
    

    看看at this,也许还有that

    第 2 版

      ; ...
      push eax ; addr of struct/class/whatever
      jmp function ; jump to function
    autolbl001:
    
      ; ...
    
    function:
      push ebp
      mov ebp, esp
      mov eax, [ebp+8] ; ebp+8 is the 32 bit value you pushed before onto the stack
      ; ...
      jmp autolbl001
    

    【讨论】:

    • 不是跳转而是调用,CALL 比 JMP 做的更多(比如推送返回地址)。另请注意,编译器理论上可以在不推送任何内容的情况下实现引用(而不是指针)。此外,调用约定和优化也非常重要(例如 fastcall)。
    • 你是对的,这是一个call,很好的电话;)。我的回答并不是要深入了解 CPU 工作方式的每一个细节,以及任何编译器所做或不做的任何事情。我只是想把它推到低层次的方向,以便更好地理解。
    猜你喜欢
    • 1970-01-01
    • 2022-01-05
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多