【问题标题】:Ignoring a return-by-reference result from a function忽略函数的引用返回结果
【发布时间】:2011-12-09 06:04:11
【问题描述】:

假设我有一个返回一个重要结果和几个不重要结果的函数。我声明了它,以便通过引用返回不重要的结果:

int CalculateStuff(int param1, int param2, int& result1, int& result2);

我想调用这个函数来计算一些东西,但在调用站点我想忽略不重要的结果。我可以这样做:

...
int dummy1, dummy2;
int result = CalculateStuff(100, 42, dummy1, dummy2);
... // do something with the result

我想考虑另一种不声明虚拟变量的方法:

int result = CalculateStuff(100, 42, *new int, *new int);

这有内存泄漏(不可接受),但比“虚拟”名称更清楚地显示我的意图(忽略结果)具有优势。

那么,如果我这样写会发生什么:

int result = CalculateStuff(100, 42, auto_ptr(new int).get(), auto_ptr(new int).get());

合法吗?执行函数代码时,临时整数是否仍然存在?我应该使用unique_ptr 而不是auto_ptr

(请不要建议重构我的代码;我可能会 - 但首先我想了解这些东西是如何工作的)

【问题讨论】:

  • 作为评论添加,因为它实际上并没有回答你的问题 - 但我通常会声明一个名为 _ 的临时文件,如果出现这种情况,我会通过它。 "CalculateStuff(100, 42, _, _); 看起来相当清晰。

标签: c++ temporary-objects return-by-reference


【解决方案1】:

这是合法的; auto_ptr 对象将保持活动状态,直到表达式结束(即函数调用)。但它丑得要命。

只需重载你的函数:

int CalculateStuff(int param1, int param2, int& result1, int& result2);
int CalculateStuff(int param1, int param2) { 
    int r1=0, r2=0; 
    return CalculateStuff(param1, param2, r1, r2);
}

【讨论】:

  • 这仍然引出了 same 问题,您将如何实现第二个重载?你打算使用虚拟变量,还是*new intauto_ptr,或者什么,这样你就可以从第二个调用第一个重载?
  • @Nawaz 例如,通过创建两个临时变量,或调用第三个实现(例如,您建议的带有指针的那个)。
  • 但这正是问题所在。
【解决方案2】:

根据 Bjarne Stroustrup 的说法,如果某些参数是可选的,那么将它们设置为指针类型是一个理想的情况,这样您就可以在不需要为它们传递参数时传递 NULL

int CalculateStuff(int param1, int param2, int * result1, int * result2);

并使用:

int result = CalculateStuff(100, 42, NULL, NULL);

所有其他选择都不会像这个一样好,或者至少不会比这个更好

当然CalculateStuff的实现要检查参数是否为NULL

【讨论】:

    【解决方案3】:

    这是我的建议:如果您必须向 SO 询问代码及其语义的正确性,那么代码无法清楚地表达您的意图

    我认为第一个版本(dummy1dummy2)是最透明的,显然是正确的。

    如果您发现自己重复调用函数并且不想要可选结果,您可以提供重载:

    int CalculateStuff(int param1, int param2, int& result1, int& result2) {}
    
    int CalculateStuff(int param1, int param2) {
      int unwanted1, unwanted2;
      return CalculateStuff(param1, param2, unwanted1, unwanted2);
    }
    

    【讨论】:

      【解决方案4】:

      如果您可以控制函数,推荐的方法是:返回包含所有结果的 std::tuple(或 boost::tuple)或编写不需要额外变量的重载。

      【讨论】:

        【解决方案5】:

        您可以创建一个类来提供到int& 的隐式(或显式)转换。

        struct ignored
        {
           int n;
           operator int&() { return n; }
        };
        
        n = CalculateStuff(a, b, ignored(), ignored());
        

        您可以进一步将其设为模板并添加 const 重载。

        【讨论】:

        • 被忽略的类型不会是const,给你带来麻烦吗?
        • @WinstonEwert:为什么?临时不能直接绑定到非常量引用。但是,可以调用临时对象的非常量方法。这就是它所利用的。
        【解决方案6】:

        合法,但不保证不泄露内存,见问题3 以here 为例。

        实现可选输出的正确和惯用方式是通过 一个指针,当你不想要结果时传递NULL,然后进行测试 在通过指针写入之前,函数中的NULL

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-09-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多