标签: rvalue-reference

避免构造函数中的const引用和rvalue引用的指数增长

我正在为一个机器学习库编写一些模板化的类,我很多时候都面临这个问题.我主要使用策略模式,其中类接收作为不同功能的模板参数策略,例如:

template <class Loss, class Optimizer> class LinearClassifier { ... }
Run Code Online (Sandbox Code Playgroud)

问题在于构造函数.随着策略量(模板参数)的增长,const引用和右值引用的组合呈指数级增长.在前面的示例中:

LinearClassifier(const Loss& loss, const Optimizer& optimizer) : _loss(loss), _optimizer(optimizer) {}

LinearClassifier(Loss&& loss, const Optimizer& optimizer) : _loss(std::move(loss)), _optimizer(optimizer) {}

LinearClassifier(const Loss& loss, Optimizer&& optimizer) : _loss(loss), _optimizer(std::move(optimizer)) {}

LinearClassifier(Loss&& loss, Optimizer&& optimizer) : _loss(std::move(loss)), _optimizer(std::move(optimizer)) {}
Run Code Online (Sandbox Code Playgroud)

有没有办法避免这种情况?

c++ rvalue-reference const-reference c++11

41
推荐指数
4
解决办法
2082
查看次数

使用右值参考成员?

我想知道一个右值引用成员有什么用

class A {
  // ...
  // Is this one useful?
  Foo &&f;
};
Run Code Online (Sandbox Code Playgroud)

与左值参考成员相比,它有任何好处或缺点吗?什么是它的主要用途?

c++ rvalue-reference c++11

39
推荐指数
2
解决办法
5054
查看次数

为什么用户定义的move-constructor会禁用隐式复制构造函数?

当我正在阅读boost/shared_ptr.hpp时,我看到了这段代码:

//  generated copy constructor, destructor are fine...

#if defined( BOOST_HAS_RVALUE_REFS )

// ... except in C++0x, move disables the implicit copy

shared_ptr( shared_ptr const & r ): px( r.px ), pn( r.pn ) // never throws
{
}

#endif
Run Code Online (Sandbox Code Playgroud)

注释"生成复制构造函数,析构函数是否正常,除了在C++ 11中,移动禁用隐式副本"是什么意思?我们是否总是自己编写副本来防止C++ 11中出现这种情况?

c++ boost copy-constructor rvalue-reference c++11

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

传递值与const&和&&重载

因此,在查找移动语义之后,我发现当您打算转移所有权时,普遍的共识是通过值传递.但在Scott Meyer关于Universal引用的讨论中,我注意到std::vector::push_back有2个重载:

void push_back( const T& value );
void push_back( T&& value );
Run Code Online (Sandbox Code Playgroud)

所以我心想,void push_back( T value );不够吗?我问了一些最终导致以下测试用例的人:

#include <memory>
#include <iostream>
#include <type_traits>

struct A
{
    A() { std::cout << "A Default constructor\n"; }
    A(const A &) { std::cout << "A Copy\n"; }
    A(A &&) { std::cout << "A Move\n"; }
};

std::aligned_storage<sizeof(A)> contents;
A& alias = *reinterpret_cast<A*>(&contents);

void ByVal(A a)
{
    new (&contents) A(std::move(a));
    alias.~A();
}

void ByLCRef(A const& a)
{
    new …
Run Code Online (Sandbox Code Playgroud)

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

37
推荐指数
3
解决办法
5199
查看次数

std::is_convertible 和 std::convertible_to 之间的区别(在实践中)?

根据en.cppreference.com(据我所知):

  • std::is_convertible被性状类需要类型FromTo为使得与返回类型的函数To返回一个From值可以通过编译。
  • std::convertible_to是一个概念,要求类型From&To如上所述,AND使得类型的r 值引用From可以转换为static_cast<To>

强加的要求std::is_convertible似乎相对简单。相反,对于 C++20 特性的简单示例中显示的这种通用概念,r 值引用转换要求std::convertible_to似乎奇怪地特定。

作为 C++ 的新手,我无法完全理解两个网页中提供的一些术语和部分补充说明,我无法想象两者的要求之间的确切区别。

一些相互关联的问题:

  • 类型From& Toof 不仅受到std::is_convertible奇怪的 r 值引用转换要求的约束,而且受到奇怪的 r 值引用转换要求的实际影响是什么?
  • 什么样的候选人类型的FromTo附加由R值参考铸件的要求被拒绝?
  • 为什么程序员可能想要使用std::is_convertiblestd::convertible_to中的一个而不是另一个作为其函数返回类型或参数类型的约束(除了概念的便利性)?

一个更简单的解释或一个例子会有所帮助。谢谢!

c++ stl rvalue-reference c++-concepts c++20

34
推荐指数
1
解决办法
1538
查看次数

非类rvalues始终具有cv不合格类型

§3.10第9节说"非类别rvalues总是有cv不合格类型".这让我很奇怪......

int foo()
{
    return 5;
}

const int bar()
{
    return 5;
}

void pass_int(int&& i)
{
    std::cout << "rvalue\n";
}

void pass_int(const int&& i)
{
    std::cout << "const rvalue\n";
}

int main()
{
    pass_int(foo()); // prints "rvalue"
    pass_int(bar()); // prints "const rvalue"
}
Run Code Online (Sandbox Code Playgroud)

根据标准,对于非类型类型没有const rvalue,但bar()更喜欢绑定const int&&.这是编译器错误吗?

编辑:显然,this也是一个const rvalue :)

编辑:这个问题似乎在g ++ 4.5.0中得到修复,现在两行打印"rvalue".

c++ rvalue rvalue-reference c++11

33
推荐指数
1
解决办法
1163
查看次数

移动构造函数应该采用const还是非const rvalue引用?

在一些地方,我已经看到了复制和移动构造函数的推荐签名,如下所示:

struct T
{
    T();
    T(const T& other);
    T(T&& other);
};
Run Code Online (Sandbox Code Playgroud)

复制构造函数采用const引用,移动构造函数采用非const rvalue引用.

据我所知,这使我无法在从函数返回const对象时利用移动语义,例如下面的情况:

T generate_t()
{
    const T t;
    return t;
}
Run Code Online (Sandbox Code Playgroud)

使用VC11 Beta进行测试,T调用复制构造函数,而不是移动构造函数.即使使用return std::move(t);复制构造函数仍然被调用.

我可以看到这是有道理的,因为tconst是不应该绑定的T&&.使用const T&&在移动构造函数签名工作正常,并且是有道理的,但你必须是因为这个问题other是常量,你不能将它的会员空出来,如果他们需要被清零了-当所有的成员都标量它只会工作或者使用正确的签名移动构造函数.

它看起来是确保在一般情况下调用移动构造t函数以便首先创建非const 的唯一方法,但我不喜欢这样做 - 构造事物是好的形式,我不希望客户T要知道他们必须反对这种形式才能提高性能.

所以,我想我的问题是双重的; 首先,移动构造函数应该采用const还是非const rvalue引用?第二:我在这种推理中是对的吗?我应该停止返回const的东西?

c++ rvalue-reference move-constructor c++11

33
推荐指数
4
解决办法
7334
查看次数

如何使模板右值引用参数仅绑定到右值引用?

我正在编写一个网络库,并大量使用移动语义来处理文件描述符的所有权.我的一个类希望接收其他类型的文件描述符包装并取得所有权,所以就像这样

struct OwnershipReceiver
{
  template <typename T>
  void receive_ownership(T&& t)
  {
     // taking file descriptor of t, and clear t
  }
};
Run Code Online (Sandbox Code Playgroud)

它必须处理多个不相关的类型,所以receive_ownership必须是一个模板,为了安全起见,我希望它只绑定到右值引用,这样用户在传递左值时必须显式地声明std :: move.

receive_ownership(std::move(some_lvalue));

但问题是:C++模板推导允许在没有额外努力的情况下传递左值.我实际上是因为不小心将左值传递给receive_ownership并且稍后使用了左值(清除)而将自己击中一只脚.

所以这是一个问题:如何使模板仅绑定到右值参考?

c++ rvalue-reference

32
推荐指数
3
解决办法
5138
查看次数

C ++标准是否保证插入关联容器失败不会修改rvalue-reference参数?

#include <set>
#include <string>
#include <cassert>

using namespace std::literals;

int main()
{
    auto coll = std::set{ "hello"s };
    auto s = "hello"s;
    coll.insert(std::move(s));
    assert("hello"s == s); // Always OK?
}
Run Code Online (Sandbox Code Playgroud)

C ++标准是否保证插入关联容器失败不会修改rvalue-reference参数?

c++ stl rvalue-reference language-lawyer pass-by-rvalue-reference

32
推荐指数
2
解决办法
1041
查看次数

发生了什么:C ++ std :: move on std :: shared_ptr增加了use_count?

我一直假设std::move()a上会std::shared_ptr窃取指针并将原始指针设置为nullptr-从而不增加引用计数。在我的世界中似乎并非如此。

设置

MacOS,g ++ -version =>“ Apple LLVM版本10.0.1(clang-1001.0.46.3)”

代码

#include <cstdio>                                                                                                                                                                                  
#include <memory>
class Thing { public: Thing(int N) : value(N) {} int value; };

void print(const char* name, std::shared_ptr<Thing>& sp)
{ printf("%s: { use_count=%i; }\n", name, (int)sp.use_count()); }

int main(int argc, char** argv) {
    std::shared_ptr<Thing>  x(new Thing(4711));
    print("BEFORE x", x);
    std::shared_ptr<Thing>  y = std::move(x);
    y->value = 4712;
    print(" AFTER x", x);
    print(" AFTER y", y);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出

编译( …

c++ macos shared-ptr rvalue-reference

31
推荐指数
1
解决办法
1277
查看次数