std :: vector.push_back(std :: move(foo))有意义吗?

时间:2018-05-08 06:26:37

标签: c++11 stl move-semantics

我在一些代码中遇到过这个问题(为清晰起见,细节已删除):

std::vector<std::vector<int>> foo;
{
    std::vector<int> bar = {42};
    foo.push_back(std::move(bar)); // Hmmm...
} // Indicate `bar` is no longer needed.

std::move看起来对我来说没用,但不是吗?行为与foo.push_back(bar);的行为有何不同?如果int而不是bar,那么该元素就像pcl::PointXYZ这样的类,就像在我的实际代码中一样?

更新:我已更改代码,以更明确地指示std::move之后未使用DigestAuthContext dcf= new DatabaseClientFactory.DigestAuthContext("admin", "admin"); DatabaseClient client = DatabaseClientFactory.newClient( "localhost", 8000, "GraphTest",dcf); MarkLogicDatasetGraph dg = MarkLogicDatasetGraphFactory.createDatasetGraph(client); String queryString = "SELECT ?person " + "WHERE { ?person <http://schema.test.com/ns/place#livesin> < https://data.test.com/loc-structure/London#this>}"; QueryExecution eq = QueryExecutionFactory.create(queryString,dg.toDataset()); ResultSet results = eq.execSelect(); while(results.hasNext()) { QuerySolution qs = results.next(); } ,因此没有非法访问等风险。< / p>

2 个答案:

答案 0 :(得分:6)

班级vector有两个push_back实施:

void push_back( const T& value );
void push_back( T&& value );

第一个复制给定的元素。

第二个尝试通过调用元素的移动构造函数(如果已定义)来“移动”它。

使用move强制选择应该重用该值的第二个实现,而不仅仅是复制一个。

在这种特殊情况下,这将会发生:

  1. 向量bar在堆栈上分配,但其元素(42)在堆上分配。
  2. 当你致电foo.push_back(...)时,foo会在堆上分配一个新的向量,这将是bar的副本。我们称之为baz :)根据调用的push_back实现,将发生以下情况:
    • void push_back( const T& value );:在这种情况下,所有bar的元素也会被复制到baz
    • 在这种情况下,{li> void push_back( T&& value ); baz将收到指向bar元素的指针,因此不会执行任何复制操作。但是,了解bar将被剥夺其元素(现在baz拥有它们)至关重要,因此bar之后move不会被使用。
  3. 什么类型的元素(普通的int或pcl::PointXYZ)并不重要,因为只有第一个向量为元素分配了内存,而指向该内存的指针是唯一的在move来电期间复制。

答案 1 :(得分:1)

  

对我来说std :: move看起来没什么问题,但是不是吗?

这取决于你的意图。

  

行为是否与foo.push_back(bar);?

不同

是的,foo.push_back(bar);会将bar复制到foo(可能会因std::vector处理动态分配而导致性能下降)。这也会使bar保持不变,之后您可以使用它。

另一方面,foo.push_back(std::move(bar));没有复制并重新使用bar中已分配的内存。请注意,这会使bar在移动后保持有效但未指定的状态(除非您重新初始化/重新分配,否则您无法使用它。)

  

如果元素不是int,那么该元素就是pcl :: PointXYZ这样的类   因为它在我的实际代码中?

Move-semantics仅对使用动态分配(拥有指针)的类类型有用。 pcl::PointXYZint不属于此类,因此std::move intstd::move pcl::PointXYZ无效。