Is it safe to operate on object within arguments' list, when there is also std::move() invoked on that object ?
void foo(int* raw, std::unique_ptr<int> u)
{
*raw = 456;
}
std::unique_ptr<int> p(new int(123));
foo(p.get(), std::move(p));
Will the `raw' pointer in foo() be valid if std::move(p) was evaluated as the first parameter ?
No, it's NOT safe. the eval order of argument is not specified in standard. So your code can be run as:
std::move(p)
. std::unique_ptr<int>
. p.get()
(because of 2., this will be nullptr
.) and pass this parameter. foo
. You have to do like this:
int *raw = p.get();
foo(raw, std::move(p));
Notice that your code can work well, because some compilers can compile your code into 3 -> 1 -> 2 -> 4. However, it doesn't mean code is safe. it's not specified standard >o<
Here are answers about argument evaluation order - In short: the order is not specified in standard and may be different per platform, compiler and calling convention.
But I wanted to test it so here are results for Cygwin GCC:
#include <iostream>
#include <memory>
using namespace std;
void print(int* p) {
cout << (p == nullptr ? "null" : "valid") << endl; }
void foo(int* p, unique_ptr<int> u) {
print(p); }
void bar(unique_ptr<int> u, int* p) {
print(p); }
__stdcall void foo2(int* p, unique_ptr<int> u) {
print(p); }
__stdcall void bar2(unique_ptr<int> u, int* p) {
print(p); }
__cdecl void foo3(int* p, unique_ptr<int> u) {
print(p); }
__cdecl void bar3(unique_ptr<int> u, int* p) {
print(p); }
int main() {
unique_ptr<int> p(new int(1)), q(new int(2));
foo(p.get(), move(p)); bar(move(q), q.get());
unique_ptr<int> p2(new int(1)), q2(new int(2));
foo2(p2.get(), move(p2)); bar2(move(q2), q2.get());
unique_ptr<int> p3(new int(1)), q3(new int(2));
foo3(p3.get(), move(p3)); bar3(move(q3), q3.get());
}
Output:
null valid null valid null valid
Surprise is that I could not force it to change the order even when I used __stdcall
and __cdecl
.
EDIT : Same test with MSVC 2012 (__stdcall/__cdecl moved before names), same result !
Calling std::move()
on arguments is perfectly safe.
What is not safe is tripping yourself up by writing to a raw pointer that was managed by an object that has relinquished the pointer's memory to the free store.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.