是否有任何未定义的行为问题,当移动数据到一个函数,然后回到它来自哪里
Are there any undefined behavior issues when moving data into a function and then back out to where it came from?
考虑以下函数:
std::vector<int> pushIt(std::vector<int> v){
v.push_back(10);
return v;
}
int main(){
std::vector<int> vec;
vec = pushIt(std::move(vec));
}
我的假设是向量被移动到函数中,修改并移动到它原来的位置。这将导致类似于将其作为非const引用传递的行为。这似乎是相当有效的行为,但同事害怕未定义的行为。我还遗漏了什么吗?
我想这样做是因为当前函数
void currentPushIt(std::vector<int>& v){
v.push_back(10);
}
在代码审查中导致了很多问题,因为人们忽略了一个事实,即对currentPushIt(v)
的无害调用可能会使迭代器无效。让他们写v=pushIt(std::move(v))
应该足以唤醒他们,使他们不再犯同样的错误。
在1.9p15中,与实参相关的值计算和副作用在执行函数体之前进行排序。所以当你输入pushIt
时,源vec
已经被移走了。然后在执行pushIt
之后对赋值进行排序,因为实际上调用的是用户定义的操作符vector::operator=
:
vec.operator=( // sequenced after
pushIt( // the evaluation of this, which is sequenced after
std::move( // the evaluation of this
vec)))
所以你的代码没问题
您的同事担心是没有理由的,所显示的代码片段没有未定义行为。
所写的代码片段,由于std::vector
是一个类,因此相当于下面的代码,并且由于函数形参在调用函数之前必须有一个值,因此相当于先调用std::move
,然后调用pushIt
,最后调用vec.operator=
。
从这种角度来看,很明显,编写这样的代码实际上是安全的。
vec.operator= (pushIt (std::move (vec));
一般
a = do_something (a);
我遇到过开发人员担心这样的代码片段,因为=
不是序列点;如果do_something
修改了a
,左边会发生什么?
长话短说;没关系。尽管我们不知道左边和右边的求值顺序,但它在正确性方面是定义好的。
=
的左边是一个左值,这可以看作是某个值最终的位置。无论存储在该位置的值是什么,实际位置都是相同的。
在这种情况下,右边将从vec
移动。这无疑会改变vec
的值,但不会改变vec
所在的位置;因此,右边的结果将被正确地赋值到它应该赋值的位置。
注意:实际赋值是排序的,lhs和rhs都必须在赋值前求值(即:在rhs的值由lhs分配给位置yield之前,但是lhs和rhs的求值顺序并不是固定的。
号是否有任何未定义的行为问题移动数据到函数,然后回到它来的地方?
函数参数在函数求值之前"顺序"求值。赋值在右侧求值之后"排序"。
- 为什么我的递归函数按降序打印,然后按升序打印?
- 等待整个 omp 块完成,然后再调用第二个函数
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- 为什么 ComPtr 的函数返回不同的值,然后 &?
- 在C++中编程,将 3 个数字发送到一个函数,然后计算这 3 个数字的平均函数
- 如何将子类作为函数的参数传递给期望基类,然后将该对象传递到指向这些抽象类对象的指针向量中?
- 如何在C++中获取lua函数作为参数,然后调用它
- 如何在类中制作 2D 数组元素,然后在其构造函数中指定其维度?
- 钩/绕道 d3d9 (现在/结束场景) - 似乎调用我的函数然后崩溃
- 使用函数打开文件,然后让其他函数利用该文件?
- C++:将向量传递给函数,然后在main中调用函数.错过了什么
- 努力将指向成员函数的指针绑定到类模板的T成员,然后在槽中调用
- 将函数应用于元组中的每个元素,将每个元素强制转换为类型包中的不同类型,然后作为参数包传递
- 是否可以将多个结构作为一个数据包存储在一个函数中,然后传递给其他函数并在那里提取?
- C++大括号初始值设定项作为参数调用不同的构造函数,然后预期
- C++ 如何创建 2D 数组,将其传递给另一个函数,然后打印
- 如何在 LLVM 传递期间破坏然后解散函数?
- 我的单例中的数组在离开函数后没有保留信息,然后在尝试再次访问信息时崩溃
- 需要在调用函数然后检查errno之前清理errno
- 声明一个没有内容的函数;-然后是内容{}- c++