标签: rvalue-reference

在C++中将非const引用传递给rvalues

在以下代码行中:

bootrec_reset(File(path, size, off), blksize);
Run Code Online (Sandbox Code Playgroud)

用原型调用函数:

static void bootrec_reset(File &file, ssize_t blksize);
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

libcpfs/mkfs.cc:99:53:错误:从'File'类型的右值开始无效初始化'File&'类型的非const引用

libcpfs/mkfs.cc:30:13:错误:传递'void bootrec_reset(File&,ssize_t)'的参数1

我知道你不能const &根据标准将非const引用()传递给rvalues.但是,MSVC允许您这样做(请参阅此问题).这个问题试图解释为什么,但答案没有意义,因为他正在使用文字的引用,这是一个极端的案例,显然应该被禁止.

在给定的示例中,可以清楚地看到将发生以下事件顺序(就像在MSVC中一样):

  1. File的构造函数将被调用.
  2. 对堆栈的引用File,和blksize,被推入堆栈.
  3. bootrec_reset利用file.
  4. 从返回后bootrec_reset,临时File被摧毁.

有必要指出File引用需要是非const的,因为它是文件的临时句柄,在其上调用非const方法.此外,我不想将File构造函数参数传递bootrec_reset给那里构造,也没有任何理由File在调用者中手动构造和销毁对象.

所以我的问题是:

  1. 什么证明C++标准以这种方式禁止非const引用?
  2. 如何强制GCC允许此代码?
  3. 即将推出的C++ 0x标准是否会改变这一点,或者新标准是否在这里提供了更合适的内容,例如所有关于rvalue引用的乱码?

c++ gcc rvalue-reference c++11

13
推荐指数
3
解决办法
7228
查看次数

将函数的返回类型声明为T &&是没有意义的吗?

众所周知,在大多数情况下,T&&意味着"这是一个临时对象".但是,如果想要从函数返回临时对象,他/她可以按如下方式声明函数:

template<class T>
T f()
{
    T t;
    ......

    return t;
}
Run Code Online (Sandbox Code Playgroud)

或(注意:不正确)

template<class T>
T&& f()
{
    T t;
    ......

    return t;
}
Run Code Online (Sandbox Code Playgroud)

但我认为后者是过度的,因为前者足够向后兼容.

然而,我也发现它std::forward()的返回类型被声明为T &&,所以我确信我对此的理解是不完整的.

我真正的问题是:我们何时何地将函数的返回类型声明为T &&?

c++ temporary return-type rvalue-reference c++11

13
推荐指数
1
解决办法
503
查看次数

成员变量的类型应该取决于构造函数参数的类型

我尝试A按如下方式定义一个类:

template< typename T >
class A
{
  public:
    A( T elem )
      : _elem( elem )
    {}

  private:
    TYPE _elem; // "TYPE" should be either "T" in case "elem" is an r-value or "T&" in case "elem" is an l-value.
};
Run Code Online (Sandbox Code Playgroud)

在这里,我希望_elem有一个类型T,以防构造函数的参数elem是一个r值或者T&case中的类型elem是一个l值.

有谁知道这是如何实现的?

c++ lvalue rvalue-reference type-deduction

13
推荐指数
1
解决办法
347
查看次数

临时对象的数据成员是C++ 11中的xvalue吗?

#include <vector>

using namespace std;

struct A
{
    vector<int> coll;
};

void f(const vector<int>&){}
void f(vector<int>&&){}

int main()
{
    f(A().coll); // Is "A().coll" an xvalue? 
}
Run Code Online (Sandbox Code Playgroud)

C++ 11保证f(A().coll)会打电话void f(vector<int>&&)吗?

c++ rvalue rvalue-reference move-semantics c++11

13
推荐指数
1
解决办法
359
查看次数

&C对C++中的参数类型有什么意义?

可能重复:
T &&在C++ 0x中意味着什么?

在我读到这个答案之前,我从未见过双安瓿.

有问题的代码段是这样的:

template <typename T>
T& as_lvalue(T&& x)
{
    return x;
}
Run Code Online (Sandbox Code Playgroud)

有什么作用&&?可以传递什么类型的参数as_lvalue()

c++ reference rvalue-reference c++11

12
推荐指数
1
解决办法
2万
查看次数

修改右值参考值 - 它是如何工作的?

下面的代码编译并运行得很好.正当我以为我开始对rvalue引用和std :: forward进行了很好的掌握 - 这个非常简单的代码揭示了rvalue有一些非常基本的东西,我不明白.请澄清.

#include <iostream>
#include <iomanip>
using namespace std;

void fn( int&& n )
{
    cout << "n=" << n << endl;
    n = 43;
    cout << "n=" << n << endl;
}


int main( )
{
    fn( 42 );
}
Run Code Online (Sandbox Code Playgroud)

我用g ++ 4.7使用以下命令行编译它:
g ++ --std = c ++ 11 test.cpp

输出为:
n = 42
n = 43

我的主要问题是编译器在函数fn中存储'n'的位置?

c++ rvalue-reference c++11

12
推荐指数
1
解决办法
977
查看次数

右值引用可以绑定到函数吗?

我用GCC,Clang,ICC和VS测试了以下代码:

void f() {}

void g(void (&&)()) { }

int main() {
    g(f);
}
Run Code Online (Sandbox Code Playgroud)

正如我们所看到的,g采用右值引用但是f是左值,并且通常,右值引用不能绑定到左值.这正是ICC抱怨的:

error: an rvalue reference cannot be bound to an lvalue
Run Code Online (Sandbox Code Playgroud)

VS也会出错,但出于另一个原因:

error C2664: 'void h(void (__cdecl &&)(void))' : cannot convert parameter 1 from 'void (__cdecl *)(void)' to 'void (__cdecl &&)(void)'
Run Code Online (Sandbox Code Playgroud)

这告诉我VS立即执行函数到指针的转换,而不是直接绑定引用f.值得一提的是,如果我替换g(f)g(&f)那么四个编译器会产生同样的错误.

最后,GCC和Clang接受了代码,我相信它们是正确的.我的推理基于8.5.3/5

对类型"cv1 T1"的引用由类型"cv2 T2"的表达式初始化为

- 如果参考是左值参考[...]

- 否则,[...] 参考应为右值参考.

     - 如果初始化表达式是 [...] 函数左值 [...]

     然后 …

c++ function rvalue-reference language-lawyer c++11

12
推荐指数
1
解决办法
595
查看次数

std :: forward如何获得正确的参数?

考虑:

void g(int&);
void g(int&&);

template<class T>
void f(T&& x)
{
    g(std::forward<T>(x));
}

int main()
{
    f(10);
}
Run Code Online (Sandbox Code Playgroud)

由于id-expression x是一个左值,并且std::forward对于左值和右值有重载,为什么调用不能绑定到std::forward需要左值的重载?

template<class T>
constexpr T&& forward(std::remove_reference_t<T>& t) noexcept;
Run Code Online (Sandbox Code Playgroud)

c++ templates rvalue-reference perfect-forwarding c++11

12
推荐指数
2
解决办法
1052
查看次数

通过rvalue-reference获取参数的所有权

我想说明我的类的构造函数A将取得传递Data参数的所有权.显而易见的事情是采用一个unique_ptr值:

class A
{
public:
    A(std::unique_ptr<Data> data) : _data(std::move(data)) { }

    std::unique_ptr<Data> _data;
};
Run Code Online (Sandbox Code Playgroud)

但是,对于我的用例,没有理由为什么Data应该是指针,因为值类型就足够了.我能想到的唯一剩下的选项,以使真正明确表示Data会为所拥有的A是路过的右值引用:

class A
{
public:
    A(Data&& data) : _data(std::move(data)) { }

    Data _data;
};
Run Code Online (Sandbox Code Playgroud)

这是一种表明所有权的有效方式,还是有更好的方法可以不使用unique_ptr

c++ rvalue-reference unique-ptr c++11

12
推荐指数
1
解决办法
934
查看次数

为什么这里的枚举变量是右值?

例子:

typedef enum Color
{
    RED,
    GREEN,
    BLUE
} Color;

void func(unsigned int& num)
{
    num++;
}

int main()
{
    Color clr = RED;
    func(clr);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译时出现以下错误:

<source>: In function 'int main()':

<source>:16:9: error: cannot bind non-const lvalue reference of type 'unsigned int&' to an rvalue of type 'unsigned int'

     func(clr);

         ^~~
Run Code Online (Sandbox Code Playgroud)

我认为clr我传递给的变量 ( )func(unsigned int&)是一个左值。我可以获得的地址clr并可以为其分配另一个值。当我尝试将它传递给 时,为什么它会变成右值func(unsigned int&)

c++ rvalue lvalue rvalue-reference c++11

12
推荐指数
1
解决办法
931
查看次数