c++ - 了解勘误表中有关 EMC++ 第 41 项的评论

标签 c++ c++11 overloading forwarding-reference effective-c++

在项目 41 中,Scott Meyers 编写了以下两个类:

class Widget {
public:
  void addName(const std::string& newName)   // take lvalue;
  { names.push_back(newName); }              // copy it

  void addName(std::string&& newName)        // take rvalue;
  { names.push_back(std::move(newName)); }   // move it; ...

private:
  std::vector<std::string> names;
};
class Widget {
public:
  template<typename T>                            // take lvalues
  void addName(T&& newName)                       // and rvalues;
  {                                               // copy lvalues,
    names.push_back(std::forward<T>(newName)); }  // move rvalues;
  }                                               // ...
private:
  std::vector<std::string> names;
};

评论中写的是正确的,即使它根本不意味着这两个解决方案是等价的,并且书中确实讨论了一些差异。

In the errata但是,作者评论了书中未讨论的另一个区别:

Another behavioral difference between (1) overloading for lvalues and rvalues and (2) a template taking a universal reference (uref) is that the lvalue overload declares its parameter const, while the uref approach doesn't. This means that functions invoked on the lvalue overload's parameter will always be the const versions, while functions invoked on the uref version's parameter will be the const versions only if the argument passed in is const. In other words, non-const lvalue arguments may yield different behavior in the overloading design vis-a-vis the uref design.

但我不确定我是否理解它。

其实写这个问题我大概是明白了,但是我还是不太确定,所以不写答案。

可能作者是说当一个非const左值传递给 addName , newNameconst在第一个代码中,非 const在第二个代码中,这意味着 if newName被传递给另一个函数(或在其上调用了一个成员函数),而不是该函数需要接受 const。参数(或成为 const 成员函数)

我的解释正确吗?

但是,我看不出这在具体示例中有何不同,因为在 newName 上没有调用任何成员函数。 , 也不会传递给对 const 具有不同重载的函数和非 const参数(不完全是: std::vector<T>::push_back 有两个重载 const T& arguments 和 T&& arguments`,但左值仍然只绑定(bind)到前一个重载...)。

最佳答案

在第二种情况下,当一个 const std::string左值传递给模板

  template<typename T>
  void addName(T&& newName)
  { names.push_back(std::forward<T>(newName)); }

实例化结果如下(我删除了 std::forward 调用,实际上是一个空操作)

  void addName(const std::string& newName)
  { names.push_back(newName); }

而如果 std::string传递左值,然后是 addName 的结果实例是

  void addName(std::string& newName)
  { names.push_back(newName); }

这意味着const std::vector<>::push_back 的版本被称为

在第一种情况下,当一个 std::string左值传递给 addName ,无论 const 是什么,都会选择第一个重载 -ness

  void addName(const std::string& newName)
  { names.push_back(newName); }

这意味着 const过载 std::vector<>::push_back在这两种情况下都被选中。

关于c++ - 了解勘误表中有关 EMC++ 第 41 项的评论,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65602182/

相关文章:

java - Retrofit 2 调用覆盖

c++ - 在C++ 11中是否有任何等于asm (“”::: “memory”)的编译器障碍?

C++ STL unordered_map 实现,引用有效性

c++ - 如何为 parallel_invoke 设置进度条?

std::move 和 std::make_move_iterator 的 C++11 编译错误

c++ - 用右值构造一对

c++ - 错误: C1083: Cannot open include file: 'boost/asio.hpp' : No such file or directory

c++ - 理解代码的问题

C++重载;相同类型的可变参数?

C++ 后递增 : objects vs primitive types