变量用作emplace_back参数后可以使用变量吗?
Is it fine to use variables after they being used as arguments of emplace_back?
可能是一个蹩脚的问题,但我总是找不到全面的答案。
std::vector::emplace_back
的参数是 r 值引用。据我了解,在通过 r 值引用传递到某处后使用对象是不安全的。我的意思是:
std::string str("hello world");
std::string str2(std::move(str)); // string::string(string &&);
cout << str; // unsafe, str was moved to str2
那么,以下示例会发生什么?
std::vector<std::string> array;
std::string str("hello world"); // what if add 'const' qualifier here?
array.emplace_back(str); // template <class... Args>
// void emplace_back (Args&&... args);
std::cout << str; // safe or not? str was moved or copied?
我在这里真的很困惑。我的测试表明,str
在emplace_back
后可以安全使用,但我(坏了?)逻辑告诉我str
被移动了,之后不应该使用。
对不起,我的英语:)不好
emplace
样式函数的参数是转发引用,这意味着它们成为左值参数的左值引用和右值参数的右值引用。
跟
array.emplace_back(str);
str
是一个左值(您尚未将其转换为带有std::move
的右值),因此它将被复制。它将在调用后保留其值。
标准库对象通常处于"有效但未指定的状态"。
有效但未指定的状态 未指定的对象的
值,除非满足对象的不变量并且对 对象的行为与其类型指定 [示例:如果类型为std::vector<int>
的对象 x 处于有效但未指定的状态,则x.empty()
可以是 无条件调用,并且只有在x.empty()
返回false
时才能调用x.front()
。—结束示例]
大多数情况下,这意味着要么为空,要么保留原始值。移动int
可能不会重置其值。
某些类型更具体,例如unique_ptr
从中移出后始终保留 nullptr。
所以,在这种情况下
std::string str("hello world");
std::string str2(std::move(str)); // string::string(string &&);
cout << str;
代码是有效的,但我们不知道输出的确切内容(如果有的话)。使它不太有用。
这个想法是,你应该让变量在被移出后超出范围,或者给它分配一个新值以进一步使用它。
emplace_back
将复制 l 值,并移动 r 值。
可以用一个简单的例子来测试这一点:
struct test {
test() {
std::cout << "Default-constructedn";
}
test(test const&) {
std::cout << "Copy-constructedn";
}
test(test &&) {
std::cout << "Move-constructedn";
}
~test() {
std::cout << "Destructedn";
}
test& operator=(test const&) {
std::cout << "Copy-assignedn";
return *this;
}
test& operator=(test &&) {
std::cout << "Move-assignedn";
return *this;
}
};
int main() {
std::vector<test> vector;
test t;
vector.emplace_back(t);//The important one
vector.emplace_back(test{});
return 0;
}
这(应该,假设复制省略号在这里不适用)会导致以下输出:
Default-constructed
Copy-constructed //The important one
Move-constructed
Destructed
Destructed
Destructed
请注意,当使用 l 值调用emplace_back
时,将调用复制构造函数。因此,在您的情况下,字符串将被复制,而不是移动,因此可以安全地在向量之外继续使用。
还值得注意的是,移动语义通常要求移自对象"处于未指定但有效的状态",这意味着使用移自对象实际上不应该是"不安全的"。不过,它仍然可能产生奇怪的效果,并且可以根据该对象的有效状态可以包含的内容调用未定义的行为(例如,如果您尝试取消引用移自unique_ptr
或其他类似对象)。
- C++:继续创建新的变量可以吗
- 多个"常量引用"变量可以共享同一个内存吗?
- 升压插值条件变量可以虚假唤醒吗?
- 是否可以使C++类成为Objc类的委托
- 标准在哪里定义了可变变量可以改变
- 是否可以使一个类成为两个不同层次结构的子类?
- 'inline'变量可以像内联函数一样内联吗?
- 将cpp_redis pub/sub与条件变量一起使用时出现问题
- 全局自动变量可以在 h 文件中声明吗?
- 在 c++ 中,全局变量可以在类中递增吗?
- 字符串比较在与变量一起使用时给出不同的输出
- 是否有编译器标志可以使较新的 gcc 版本像旧版本一样构建
- C 可以使destuructor不称为班级成员和基类攻击方的灾难
- 静态变量可以多次初始化吗?
- 变量可以通过C / C 的左或右移动操作变为null
- 可以使未命名的结构静态
- 对于具有两个模板化变量的模板化类,是否可以使一个 var 引用另一个 var
- 如何使函数中的变量可以被主函数访问
- 是否可以使函数对于常量参数或变量参数的行为不同
- 我可以使一些变量模板特定