如何将左值转换为右值?以及“新”标签会发生什么
How do you convert a lvalue to an rvalue? And what happens to the `new` lvalue?
我想使用 std::vector::push_back()
将对象移动到std::vector
中。 这似乎是可能的,因为有一个std::vector::push_back(value_type&& val)
函数。 但是由于存在 std::vector::push_back(value_type const & val)
,它复制并且将是覆盖调用,我需要将左值对象转换为右值。
这是怎么做到的?
例:
struct X { int x; X(int x) : x(x) {} };
int main()
{
std::vector<X> ax;
X x(3);
ax.push_back(x); // <= Want to move x in to vector ax, not copy.
return 0;
}
其实,也许不可能? 我问这个是因为写完这个例子后,我的新问题是:
- 如果我真的把
x
搬到ax
,x.x
的价值是什么? 如果X
有一个显式析构函数,那么当x
离开范围时会发生什么?
只需使用 std::move()
:
ax.push_back(std::move(x));
关于您的问题:
如果我确实将 x 移动到 ax 中,x.x 的值是多少?
在这种情况下,您的类X
不包含显式声明的 move 构造函数,因此编译器将生成一个对 X
的成员进行成员移动的构造函数。由于X
只有一个类型为 int
的成员,并且移动int
与复制它没有什么不同,因此x.x
将具有与移动之前相同的值。
如果 X 有一个显式析构函数,那么当 x 离开范围时会发生什么?
如果X
具有用户声明的析构函数,这将禁止生成隐式移动构造函数 - 但不会禁止生成隐式复制构造函数。因此,此函数调用:
ax.push_back(std::move(x));
将导致x
被复制到ax
中。在任何情况下,x
在超出范围时都会被销毁,因为它具有自动存储持续时间 - 无论是否存在用户声明的析构函数。
一般来说,人们不应该对已移动的对象的状态做出假设,除非该状态是有效的(C++11标准的第17.6.5.15/1段保证了标准库的类型也是如此(。
具体而言,这意味着唯一可以安全地处理已移动对象的函数是那些对该对象的状态没有任何先决条件的函数。通常,两个这样的函数是析构函数和(复制或移动(赋值运算符。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 警告处理为错误这里有什么问题
- 什么时候调用组成单元对象的析构函数
- #定义c-预处理器常量..我做错了什么
- 努力将整数转换为链表。不知道我在这里做错了什么
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 什么时候在C++中返回常量引用是个好主意
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- C++避免重复声明的语法是什么
- c++库的公共头文件中应该包含什么
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 对两个案例标签使用相同的值与对单个案例使用多个案例标签有什么区别?
- 什么会导致"静态"标签在窗口上不显示WS_VISIBLE
- C++中的标签和枚举调度有什么区别
- 什么是签名目录文件成员标签
- 在交换机的默认标签中放置什么
- 如何将左值转换为右值?以及“新”标签会发生什么
- 我可以使用什么Mac/iOS/便携式库来格式化信息以打印到标签纸上
- 当.h和.cpp Doxygen标签冲突时会发生什么?
- 我们应该在 c++ 类中指定"private"标签吗?有什么区别吗?