我在一些代码中遇到过这个问题(为清晰起见,细节已删除):
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>
答案 0 :(得分:6)
班级vector
有两个push_back
实施:
void push_back( const T& value );
void push_back( T&& value );
第一个复制给定的元素。
第二个尝试通过调用元素的移动构造函数(如果已定义)来“移动”它。
使用move
强制选择应该重用该值的第二个实现,而不仅仅是复制一个。
在这种特殊情况下,这将会发生:
bar
在堆栈上分配,但其元素(42)在堆上分配。foo.push_back(...)
时,foo
会在堆上分配一个新的向量,这将是bar
的副本。我们称之为baz
:)根据调用的push_back
实现,将发生以下情况:
void push_back( const T& value );
:在这种情况下,所有bar
的元素也会被复制到baz
。void push_back( T&& value );
baz
将收到指向bar
元素的指针,因此不会执行任何复制操作。但是,了解bar
将被剥夺其元素(现在baz
拥有它们)至关重要,因此bar
之后move
不会被使用。什么类型的元素(普通的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::PointXYZ
和int
不属于此类,因此std::move
int
或std::move
pcl::PointXYZ
无效。