gpt4 book ai didi

c++ - 将正在 move 的对象的成员作为参数传递是否安全

转载 作者:可可西里 更新时间:2023-11-01 18:35:42 25 4
gpt4 key购买 nike

#include <iostream>
#include <string>
#include <map>

struct A {
int n { 42 };
std::string s { "ciao" };
};

int main() {
A a;
std::map<std::string, A> m;
std::cout << "a.s: " << a.s << std::endl; // print: "a.s: ciao"
m.emplace(a.s, std::move(a)); // a.s is a member of a, moved in the same line
std::cout << "in map: " << m.count("ciao") << std::endl; // print: "in map: 1"
std::cout << "a.s: " << a.s << std::endl; // print: "a.s: " (as expected, it has been moved)
}

将“move ”对象的成员作为参数传递是否安全?在这种情况下,emplace 似乎有效: map 具有预期的键。

最佳答案

很有趣。出于复杂的原因,我认为这是安全的。 (郑重声明,我也认为它的风格很糟糕 -- 显式复制在这里不花任何钱,因为它会被移到 map 中。)

首先,实际的函数调用是没有问题的。 std::move只投 a到右值引用,右值引用只是引用; a 没有立即 move 。 emplace_back将其参数转发给 std::pair<std::string, A> 的构造函数,这就是事情变得有趣的地方。

那么,std::pair 的哪个构造函数?用来?它有很多,但有两个是相关的:

pair(const T1& x, const T2& y);
template<class U, class V> pair(U&& x, U&&y);

(参见标准中的 20.3.2),其中 T1T2std::pair 的模板参数.根据 13.3,我们以 U == const T1& 结束在后者中。和 V == T2 ,这很直观(否则实际上不可能进入 std::pair)。这给我们留下了一个构造函数

pair(const T1& x, T2 &&y) : first(std::forward(x)), second(std::forward(y)) { }

按照 20.3.2 (6-8)。

那么,这样安全吗?很有帮助,std::pair有一些详细的定义,包括内存布局。特别是,它指出

T1 first;
T2 second;

按照这个顺序来,所以first将在 second 之前初始化.这意味着在您的特定情况下,字符串将在移走之前被复制,这样您就安全了。

但是,如果你反过来做:

m.emplace(std::move(A.s), A); // huh?

...然后你会得到有趣的效果。

关于c++ - 将正在 move 的对象的成员作为参数传递是否安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27266755/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com