简体   繁体   English

了解关于 EMC++ 第 41 项的勘误表的评论

[英]Understanding comment from the errata about Item 41 of EMC++

In Item 41, Scott Meyers writes the following two classes:在 Item 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;
};

What's written in the comments is correct, even if it doesn't mean at all that the two solutions are equivalent, and some of the differences are indeed discussed in the book.评论中写的是正确的,即使这并不意味着这两种解决方案是等价的,并且书中确实讨论了一些差异。

In the errata , however, the author comments another difference not discussed in the book:然而,在勘误表中,作者评论了书中未讨论的另一个差异:

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. (1) 左值和右值的重载与 (2) 采用通用引用 (uref) 的模板之间的另一个行为差异是左值重载声明了它的参数const ,而 uref 方法没有。 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 .这意味着在左值重载的参数上调用的函数将始终是const版本,而在 uref 版本的参数上调用的函数只有在传入的参数是const时才会是const版本。 In other words, non- const lvalue arguments may yield different behavior in the overloading design vis-a-vis the uref design.换句话说,非const左值 arguments 可能在重载设计与 uref 设计中产生不同的行为。

But I'm not sure I understand it.但我不确定我是否理解。

Actually, writing this question I've probably understood, but I'm not writing an answer as I'm still not sure.实际上,写这个问题我可能已经理解了,但我没有写答案,因为我仍然不确定。

Probably the author is saying that when a non- const lvalue is passed to addName , newName is const in the first code, and non- const in the second code, which means that if newName was passed to another function (or a member function was called on it), than that function would be required to take a const parameter (or be a const member function) .可能作者是说当一个非const左值被传递给addName时, newName在第一个代码中是const ,而在第二个代码中是非const ,这意味着如果newName被传递给另一个 function (或成员 function 是调用它),而不是 function 需要采用const参数(或成为const成员函数)

Have I interpreted correctly?我的解释是否正确?

However, I don't see how this makes a difference in the specific example, since no member function is called on newName , nor it is passed to a function which has different overloads for const and non- const parameters (not exactly: std::vector<T>::push_back has two overloads for const T& arguments and T&& arguments`, but an lvalue would still bind only to the former overload...).但是,我看不出这在具体示例中有何不同,因为在newName上没有调用成员 function ,也没有将其传递给对const和非const参数具有不同重载的 function (不完全是: std::vector<T>::push_back有两个重载const T& arguments 和T&& arguments`,但左值仍然只绑定到前一个重载......)。

In the second scenario, when a const std::string lvalue is passed to the template在第二种情况下,当将const std::string左值传递给模板时

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

the instantiation results in the following (where I've removed the std::forward call as it is, in practice, a no-op)实例化结果如下(我已经删除了std::forward调用,实际上,它是无操作的)

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

whereas if a std::string lvalue is passed, then the resulting instance of addName is而如果传递了一个std::string左值,那么addName的结果实例是

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

which means that the non- const version of std::vector<>::push_back is called .这意味着调用std::vector<>::push_back的非const版本

In the first scenario, when a std::string lvalue is passed to addName , the first overload is picked regardless of the const -ness在第一种情况下,当std::string左值传递给addName时,无论const -ness如何,都会选择第一个重载

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

which means that the const overload of std::vector<>::push_back is selected in both cases.这意味着在这两种情况下都选择了std::vector<>::push_backconst重载。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM