C 术语中的 C++ 右值引用?
C++ r-value reference in C terms?
我不知道我问的是不是一个好问题,但我真的很好奇这个问题。除了 C++ 中引入的这个新的 r 值引用之外的所有内容,我都可以用 C 术语翻译和理解。不是每个人都会同意我的看法,但对我来说,C++ 是一个高度复杂的 C 宏扩展。
好的,我想知道的是,例如,如果您按如下方式查看构造函数和析构函数,
{
struct Object {
char* s;
Object(size_t n) { s = new char[n]; }
~Object() { delete[] s; }
} o(10);
}
您可以期望编译器像处理代码一样,
{
struct Object { char* s; } o;
new_Object(&o, 10); /* o->s = malloc(10); */
delete_Object(&o); /* free(o->s); */
}
我并不是说 C++ 编译器必须进行这种翻译。我只是相信 C++ 被设计成这样工作,以便与现有的 C 应用程序顺利集成并吸引 C 开发人员。
无论如何,一个普通的左值引用可以被理解为,而且实际上很可能是一个抽象的指针。对于编译器,它应该与
相同
int n = 1;
int& m = n;
m = 2;
和
int n = 1;
int* m = &n;
*m = 2;
但是 r 值引用呢?谁能解释一下如何用 C 术语理解 r 值引用和 std::move
?
它与左值引用相同,只是它只能绑定到右值。
一个例子可能是:
typedef struct S { int x; } S;
S foo() { S s; return s; }
S && r = foo();
最后一行的 C 等效项可能是:
S *p = &(foo());
除了 C 有一条规则,您不能将 &
应用于右值,而且函数调用的 return 值不会持续到函数调用的语句末尾.
所以你必须这样写:
S temp = foo();
S *p = &temp;
int a = 1, b = 2;
a // this is an lvalue - you can assign to it
(a + b) // this is an rvalue - you cannot assign to it
&a // this is a kind of lvalue reference - a pointer
&(a + b) // so this would be an rvalue reference, if C supported it
右值引用允许您表示表达式的中间结果,并且还知道这些结果是临时的(右值),因此它们不会被进一步使用。
如果你收到让我们说 std::vector<int>
作为函数的右值引用参数,你知道它会在函数 returns 之后立即被破坏,所以如果你想存储它的内容你可以只使用 swap
。这对于左值引用是不可能的 - 向量仍然可以在你的函数之后使用 returns 并且你会破坏一些东西。
如果您熟悉 std::auto_ptr
,那么右值引用与将 std::auto_ptr
作为参数传递值非常相似,它表达了 "callee takes responsibility of deleting the passed object" 的语义。主要区别在于,如果您将非左值表达式的结果传递给函数,编译器会自动为您创建右值引用。
std::move
允许您从通常是左值引用的内容创建右值引用。它本质上说 "I'm not going to use this anymore, callee can do whatever it wants with this".
我不知道我问的是不是一个好问题,但我真的很好奇这个问题。除了 C++ 中引入的这个新的 r 值引用之外的所有内容,我都可以用 C 术语翻译和理解。不是每个人都会同意我的看法,但对我来说,C++ 是一个高度复杂的 C 宏扩展。
好的,我想知道的是,例如,如果您按如下方式查看构造函数和析构函数,
{
struct Object {
char* s;
Object(size_t n) { s = new char[n]; }
~Object() { delete[] s; }
} o(10);
}
您可以期望编译器像处理代码一样,
{
struct Object { char* s; } o;
new_Object(&o, 10); /* o->s = malloc(10); */
delete_Object(&o); /* free(o->s); */
}
我并不是说 C++ 编译器必须进行这种翻译。我只是相信 C++ 被设计成这样工作,以便与现有的 C 应用程序顺利集成并吸引 C 开发人员。
无论如何,一个普通的左值引用可以被理解为,而且实际上很可能是一个抽象的指针。对于编译器,它应该与
相同int n = 1;
int& m = n;
m = 2;
和
int n = 1;
int* m = &n;
*m = 2;
但是 r 值引用呢?谁能解释一下如何用 C 术语理解 r 值引用和 std::move
?
它与左值引用相同,只是它只能绑定到右值。
一个例子可能是:
typedef struct S { int x; } S;
S foo() { S s; return s; }
S && r = foo();
最后一行的 C 等效项可能是:
S *p = &(foo());
除了 C 有一条规则,您不能将 &
应用于右值,而且函数调用的 return 值不会持续到函数调用的语句末尾.
所以你必须这样写:
S temp = foo();
S *p = &temp;
int a = 1, b = 2;
a // this is an lvalue - you can assign to it
(a + b) // this is an rvalue - you cannot assign to it
&a // this is a kind of lvalue reference - a pointer
&(a + b) // so this would be an rvalue reference, if C supported it
右值引用允许您表示表达式的中间结果,并且还知道这些结果是临时的(右值),因此它们不会被进一步使用。
如果你收到让我们说 std::vector<int>
作为函数的右值引用参数,你知道它会在函数 returns 之后立即被破坏,所以如果你想存储它的内容你可以只使用 swap
。这对于左值引用是不可能的 - 向量仍然可以在你的函数之后使用 returns 并且你会破坏一些东西。
如果您熟悉 std::auto_ptr
,那么右值引用与将 std::auto_ptr
作为参数传递值非常相似,它表达了 "callee takes responsibility of deleting the passed object" 的语义。主要区别在于,如果您将非左值表达式的结果传递给函数,编译器会自动为您创建右值引用。
std::move
允许您从通常是左值引用的内容创建右值引用。它本质上说 "I'm not going to use this anymore, callee can do whatever it wants with this".