1

I am writing cmu 15-445 projects0, when i convert 'unique_ptr' to 'shared_ptr', i got "Moving a temporary object prevents copy elision" error, here is my code.

Trie new_trie = Trie(std::shared_ptr<TrieNode>(std::move(root_->Clone())));
// root_->Clone() is unique_ptr<TrieNode> type

and here is the defination of TrieNode and Clone

class TrieNode {
 public:
  // Create a TrieNode with no children.
  TrieNode() = default;

  // Create a TrieNode with some children.
  explicit TrieNode(std::map<char, std::shared_ptr<const TrieNode>> children) : children_(std::move(children)) {}

  virtual ~TrieNode() = default;

  // Clone returns a copy of this TrieNode. If the TrieNode has a value, the value is copied. The return
  // type of this function is a unique_ptr to a TrieNode.
  //
  // You cannot use the copy constructor to clone the node because it doesn't know whether a `TrieNode`
  // contains a value or not.
  //
  // Note: if you want to convert `unique_ptr` into `shared_ptr`, you can use `std::shared_ptr<T>(std::move(ptr))`.
  virtual auto Clone() const -> std::unique_ptr<TrieNode> { return std::make_unique<TrieNode>(children_); }

  // A map of children, where the key is the next character in the key, and the value is the next TrieNode.
  std::map<char, std::shared_ptr<const TrieNode>> children_;

  // Indicates if the node is the terminal node.
  bool is_value_node_{false};

  // You can add additional fields and methods here. But in general, you don't need to add extra fields to
  // complete this project.
};

here is the error

Moving a temporary object prevents copy elision (fix available)clang(-Wpessimizing-move)

I am using clang-14 and vscode, vscode's quick fix let me delete std::move, but why? As far as i know, unique_ptr can't be passed as a parameter directly.

BaotongJin
  • 11
  • 3
  • 3
    at a guess `root->Clone()` returns by value, it's therefore already an `rvalue` and `std::move` is superfluous – Alan Birtles Mar 16 '23 at 13:31
  • Given the name of the function `Clone()` one has to assume that new object is returned there. In some sense this can be automatically moved, because the compiler knows the object doesn't exist in any other form. – alfC Mar 16 '23 at 13:37
  • That's not an error, just a warning that you elevated to an error with `-Werror` or something like that. The code is fine in both cases and there is no difference in performance in this case either. However the warning is correct that applying `std::move` to the return value of a function that returns by-value or by-rvalue-reference is always a pessimization at worst or a complete noop otherwise. A function call expression returning anything but a lvalue reference is already a rvalue expression and the only purpose of `std::move` is to turn an lvalue expression into a rvalue expression. – user17732522 Mar 16 '23 at 13:41

0 Answers0