- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
在 C++03 中编程时,我们不能将未命名的临时 T()
传递给函数 void foo(T&);
。通常的解决方案是给临时命名,然后像这样传递它:
T v;
foo(v);
现在,C++0x 出现了——现在有了右值引用,定义为 void foo(T&&)
的函数将允许我传递一个临时值。这让我想到了我的问题:既然一个接受右值引用的函数既可以接受右值引用(未命名的临时对象)也可以接受左值引用(命名的非常量引用),是否有任何理由在函数参数中再使用左值引用?我们不应该总是使用右值作为函数参数吗?
当然,一个接受左值引用的函数会阻止调用者传递一个临时值,但我不确定这是否是一个有用的限制。
最佳答案
“因为采用右值引用的函数既可以采用右值引用(未命名的临时对象)也可以采用左值引用(命名的非常量引用)”
这是一个错误的陈述。在右值引用规范的第一次迭代中,这是正确的,但它不再是并且至少在 MSVC 中实现以符合后来的变化。换句话说,这是非法的:
void f(char&&);
char x;
f(x);
为了调用一个期望右值引用的函数,你必须像这样把它变成一个右值:
f(std::move(x))
当然,该语法清楚地表明了一个函数采用左值引用和一个采用右值引用的函数之间的真正区别是:右值引用不希望在调用中继续存在。这是一件大事。
现在,您当然可以创建一个新函数来完全执行 std::move 所做的工作,然后您“可以”使用类似于左值引用的右值引用。例如,当您根本不关心访问者调用的任何结果时,我考虑过使用访问者框架执行此操作,但有时您会这样做,因此在这些情况下需要左值引用。使用右值引用,我可以同时得到这两者……但这违反了右值引用语义,我认为这是个坏主意。
基于此,您的陈述可能会造成混淆:
template < typename T >
void f(T&&);
char x;
f(x);
这可行,但不是因为您将左值作为右值引用传递。它的工作原理是引用衰减(C++0x 中也是新的)。当您将左值传递给这样的模板时,它实际上会像这样被实例化:
void f<char&>(char&&&);
引用衰减表明 &&&
变成 &
所以实际的实例化看起来像这样:
void f<char&>(char&);
换句话说,您只是通过引用传递一个左值......这没什么新的或特别的。
希望能解决问题。
关于C++0x : rvalue reference versus non-const lvalue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4521524/
They say Rvalues 的成员也是 Rvalues - 这很有意义。所以这要么是 VC++ 特有的错误,要么是我对右值理解的错误。 拿这个玩具代码: #include #include
(我搜索了[c++]“c++中的函数式编程”一书,只给出了4个不相关的结果。) 我正在阅读来自 Ivan Čukić 的 C++ 函数式编程 , 在第 118 页有一句话我不确定我是否理解。该节是关于
以下代码无法编译。 Clang 给出此错误消息:候选函数不可行:第一个参数没有从“A”到“A &&”的已知转换 这就好像 f() 中的 a 是一个左值。 struct A{}; void g(A&&
假设我有以下对象 class foo { foo() {..} //Constructor foo(const foo& f) {..} //Copy
我最近一直在玩 Rvalue 引用,但遇到了一个奇怪的问题。让我们定义一些名为 Foo 的简单类,其中包含一个 vector : class Foo { public: Foo(std::ve
RValue 引用的堆栈大小是多少? 例如在这样的情况下: struct A { /* ... */ }; A getA() { A temp; return
RValue 引用的堆栈大小是多少? 例如在这样的情况下: struct A { /* ... */ }; A getA() { A temp; return
现在我有一个只有一个构造函数的类 ShaderProgram(std::initializer_list> shaders); 我正在使用引用包装器,因为我没有引用的 initializer_list
我一直在努力理解移动构造函数场景背后发生的事情,但我的脑海中缺少了一些东西。 struct A { int s; A() : s(10) {} A(const A&
我有一个可变模板函数 template inline void ReadStream::decode(ARGS&...args) { internalDecode(args...); } tem
RValues 是不可操作的内存区域,因此像整数这样的文字被认为是 RValues。 常量构成 RValues 吗? const int x = 0; 至少可操作一次。 现在,编译器创建的临时对象也是
“*this 的右值引用”最典型的用例是什么?标准也将其称为成员函数的引用限定符? 顺便说一下,关于这个语言特性有一个非常好的解释 here 。 最佳答案 调用时,每个成员函数都有一个 *this 引
我有一个带有值的 vector : obj={1.0,2.0,3.0, 4.0,5.0,6.0 ,7.0,8.0,9.0,10.0} 假设,在数学上 obj 被划分为三个子 vector : obj=
考虑以下 C++ 代码 template void f (const int x, const int y, Args&&... args) { // Do something } 据我了解,这
考虑以下代码: int three() { return 3; } template class Foo { private: T* ptr; public: void ba
在 clang 的 C++11 status page 中遇到了一个名为“*this 的右值引用”的提议. 我已经阅读了很多关于右值引用的内容并理解了它们,但我认为我对此一无所知。我在网络上也找不到太
我遇到了下面的代码,但我在谷歌上找不到为什么下面的语句是有效的 C++: Base&& b = Derived(); 请解释或给出引用 这是一个示例代码: #include using namesp
在 clang 的 C++11 status page 中遇到了一个名为“*this 的右值引用”的提议. 我已经阅读了很多关于右值引用的内容并理解了它们,但我认为我对此一无所知。我在网络上也找不到太
我遇到了 RValue 不允许隐式转换的问题。我的问题是什么实现更好地“绕过”这个限制? 下面是说明问题的示例代码: template class ITestClass { public: vir
我想知道这怎么可能? template void Test(T&& arg) { arg = 14; } int a = 23; Test(a); 我的问题是函数 Test 需要一个右值类型的
我是一名优秀的程序员,十分优秀!