簡體   English   中英

局部變量的右值引用和移動

[英]rvalue reference and move of a local variable

在這個片段中,我分配了一個本地 object B,我將它傳遞給另一個 object C 的構造函數,它將它作為右值引用。 然后我將后者放入容器中。

當我檢索 C 並將其成員 static_cast 回 B 時,該值不正確(並且 valgrind 識別出 18 個錯誤!)

#include <iostream>
#include <memory>
#include <vector>

class A {
public:
  virtual ~A() {};
};

class B: public A {
public:
  B(int foo) : _foo(foo) {}
  int _foo;
};

class C {
public:
  C(A&& a): _a(std::move(a)) {}
  A&& _a;
};

std::vector<C> v;

void bar() {
  v.emplace_back(B(12));
}

int main() {
  bar();
  C&& c = std::move(v.front());
  std::cout << static_cast<B&&>(c._a)._foo << std::endl;
  return 0;
}

我的理解是,由於 C 采用右值引用,因此不應有任何 object 切片。 我應該仍然能夠檢索到完整的 B object。 此外,我對std::move的理解(很可能是有缺陷的)是我可以將局部變量“移動”出其上下文,並且通過獲取右值引用,C 獲得 B 的所有權。

output 是39931504而不是12

任何人都可以向我解釋發生了什么?

我應該仍然能夠檢索到完整的 B object。

如果它不是在控制到達bar的右括號時不存在的臨時變量,那么您會是。 您在C中持有參考,而對臨時 object 的參考很快就會變得懸空。

一個快速的解決方法是簡單地將C的成員聲明更改為std::unique_ptr<A> a; 並正確地初始化它,比如說,

template<class AChild> C(AChild child)
  : a(std::make_unique<AChild>(std::move(child))) {};

(按口味添加 SFINAE)。

問題是 class C中對A的引用(即數據成員_a )比它所指的 object 的壽命更長。 這是因為bar()中的臨時B(12) ) function

void bar() {
   v.emplace_back(B(12));
}

bar()返回后不存在。 因此, class C包含的對A的引用成為懸空引用


您可以使用new運算符創建B object 而不是臨時的:

void bar() {
   B* ptr = new B(12);
   v.emplace_back(std::move(*ptr));
}

bar()返回時,此B object 不會停止存在,因此C中對A的引用仍然有效。

請注意,使用這種方法,您需要手動銷毀 object:

C&& c = std::move(v.front());
// ...
delete &c._a; // destroy object

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM