C ++返回一个字符串引用并在同一个函数中传递一个字符串引用

时间:2014-07-09 08:55:40

标签: c++ arguments return-type

我和我的上级一直在争论这个功能:

const std::string &GetCurrentDataSourceName(std::string & sName)
{
   sName = GetAnotherComponent().GetName();
   return  sName;
}

是否有任何原因可以包含函数返回类型和参数类型?该函数的目的是返回1个值。

他的动机和用例是人们可以做到这一点:

std::string sName = "";
SetSomeValue(GetCurrentDataSourceName(sName));

我认为最好省略这样的参数:

const std::string &GetCurrentDataSourceName()
{
   return  GetAnotherComponent().GetName();
}

但他让我怀疑自己的编码能力。

编辑: 返回的值必须是const。代码也已更新,以显示返回值的来源。我来自同一个类中的另一个组件;

4 个答案:

答案 0 :(得分:7)

原始功能看起来像一个丑陋的黑客。它肯定会从阅读代码的任何人那里调用“WTF”,因此它应该可以避免。

请注意,您的替换依赖somevalue作为全局对象或类似对象。如果不是这种情况(即如果在函数内部计算somevalue),那么你将返回一个悬空参考 - 错误代码。

我认为最干净的方法是摆脱一线启用黑客,依靠移动语义和/或[N]RVO来完成他们的工作,然后按价值返回:

std::string GetCurrentDataSourceName()
{
   return somevalue;
}

答案 1 :(得分:5)

似乎函数的重点只是获取一些字符串值,在这种情况下我只会这样写:

std::string GetCurrentDataSourceName() {
  return somevalue;
}

除非您有充分理由将const引用返回somevalue,否则只需按值返回。如果在函数中计算somevalue并且您刚刚省略,那么肯定不会返回引用。

我认为没有充分的理由拥有输出参数。你的上司的例子可以这样写:

std::string sName = GetCurrentDataSourceName();
SetSomeValue(sName);

我也觉得这更容易阅读。

答案 2 :(得分:2)

您建议的代码......

const std::string &GetCurrentDataSourceName()
{
   return  somevalue;
}

...令人担忧,因为它返回对变量的引用,这意味着您必须对somevalue的生命周期和潜在进一步更改/无效与潜在客户端使用情况有关的深入见解和保证

如果您碰巧返回一个引用来表示static const std::string存储“组件”名称(如您编辑的问题所暗示的那样),那就没关系了,但它通常不是您想要的东西因为通常引用返回是偶然的,并且引用是一个(调用)函数局部变量,当函数返回时超出范围,所以任何看到上面返回类型的人都会立即对函数感到紧张,至少希望仔细检查实施情况或确保文件提供相关保证。

一般来说,编码更好......

std::string GetCurrentDataSourceName() // "const" here if a member function
{
   return ...somevalue..;
}

...哪个 - 如果还需要设置局部变量 - 那么可以这样使用:

SetSomeValue(sName = GetCurrentDataSourceName());

它也更方便,因为调用者不一定需要一个命名的局部变量,如果他们只想要例如将数据源名称传递给另一个函数,在表达式中使用它(例如,添加前缀/引用,转义它以便在URL中使用),或者将其传输到某个地方。

在这种情况下,表面上没有理由同时接受将变量设置为by-reference参数并返回新值。

答案 3 :(得分:1)

我不认为在一行中方便连接函数调用'是这样做的正当理由。

按值而不是const引用更好地返回。特别是当你可以使用c ++ 11时。

std::string GetCurrentDataSourceName(std::string sName)
{
    //do some work with sName..
    return sName;
}

既然你要修改sName,那么无论如何你都要复制,使用移动语义,你可以像这样用函数调用保存复制开销:

sName = GetCurrentDataSourceName(std::move(sName)); //no copy required