【问题标题】:Why do C++ allow constant to be transformed to reference argument in another method?为什么 C++ 允许将常量转换为另一种方法中的引用参数?
【发布时间】:2010-12-29 18:48:30
【问题描述】:
void outputString(const string &ss) {
    cout << "outputString(const string& ) " + ss << endl;
}

int main(void) {
    outputString("constant tranformed to reference argument");
    //! outputString(new string("abc")); new only return pointer to object
    return 0;
}

既然禁止创建临时对象引用转换为方法,这种语法应该是没用的,反而会让事情变得更加混乱。那么C++为什么要费心支持这种语法呢?

编辑:说实话,我没看懂你的表述。考虑到上面的例子,我们通常会使用void outputString(const string ss)而不是void outputString(const string &amp;ss)。我认为正常的事情是'通过“按值”方法处理常量/变量,而“按引用传递”方法只处理变量。我们应该使用const type-id &amp; 而不是const type-id 处理常量的唯一原因是效率,因为“按引用传递”方法只采用原始常量/对象变量的指针(地址),但“按值传递”方法需要进行复制。

谢谢。

【问题讨论】:

  • 你对价值传递的看法是完全错误的。通过 const 引用传递是 C++ 首选的处理方式,除了 int 和 double 等“内置”类型。
  • 如果您认为按值传递是常态,我建议您查看任何规模合理的 C++ 项目的代码。
  • 您应该通过值传递一个重要对象的唯一时间是您希望函数始终在副本上工作。即使这样,通常最好还是通过引用传递,然后在函数定义中创建一个工作副本。
  • @Mike DeSimone 为什么它通常更好?如果您通过值传递,如果它来自右值,则编译器可能会完全忽略副本

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


【解决方案1】:

只允许为 const 参数创建临时引用。如果参数不是 const 引用,那么您可以更改方法中的数据,而不会意识到您的引用是数据的临时副本,因此被禁止。

但是,当它是 const 引用时,您无法更改数据,因此它是对副本的引用并且如此安全并不重要,因此正如您的示例所示,它很有用。

【讨论】:

    【解决方案2】:

    你有什么选择?

    void outputString(const string ss);
    

    这将创建任何传递的字符串的副本,即使类型完全匹配:开销并不是真正需要的!

    void outputString(string &ss);
    

    这将允许更改传递的参数。我们不想那样做,而且 C++ 不允许我们再传递一个临时值,以保护我们免于更改一个临时值(无论如何,这些更改在接下来的时刻都会丢失)。

    所以,它的方式适合两个方面:它允许我们传递非临时字符串而不复制它们,它允许我们传递临时字符串。 而且它保护我们免于试图改变论点。似乎是一个很好的妥协。

    【讨论】:

    • 但对于临时字符串,没有区别。
    • @jcyang,没错。 string const&amp;string const 版本都将采用相同的临时字符串类型。但是,在下一个 C++ 版本中,第一个版本不会复制临时文件——这意味着不再需要访问复制构造函数。在当前的 C++ 中,两个版本都需要临时可复制,即使副本已优化。
    【解决方案3】:

    你在哪里修改ss

    cout << "outputString(const string& ) " + ss << endl;
    

    这一行在底层创建了一个临时的而不修改const&amp;对象ss

    编译器通常会这样做:

    string tmp = "outputString(const string& ) " + ss;
    cout << tmp << endl;
    

    【讨论】:

      【解决方案4】:

      您的意思是,它允许将 literals 转换为 const 对象引用。

      这很重要。否则你将不得不写 OutputString(std::string("literal")) ,这会很烦人。人们会发现自己对接受 std::string 和 char* 的方法进行了单独的重载。

      【讨论】:

      • 不,文字被隐式转换为临时 std::string。然后将该临时值作为 const 引用传递。
      猜你喜欢
      • 2013-07-07
      • 1970-01-01
      • 2011-08-20
      • 1970-01-01
      • 2019-01-10
      • 2020-08-22
      • 1970-01-01
      • 2021-12-27
      • 1970-01-01
      相关资源
      最近更新 更多