标签: rvalue-reference

标准库容器在GCC中的rvalues上生成大量副本

我正在为linux和windows编写一个应用程序,并注意到GCC构建产生了许多对复制构造函数的无用调用.

以下是产生此行为的示例代码:

struct A
{
    A()                { std::cout << "default" << std::endl; }
    A(A&& rvalue)      { std::cout << "move"    << std::endl; }
    A(const A& lvalue) { std::cout << "copy"    << std::endl; }
    A& operator =(A a) { std::cout << "assign"  << std::endl; return *this; }
};

BOOST_AUTO_TEST_CASE(test_copy_semantics)
{
    std::vector<A> vec_a( 3 );
}
Run Code Online (Sandbox Code Playgroud)

此测试仅创建3个元素的向量.我期望3个默认构造函数调用和0个副本,因为没有A左值.

在Visual C++ 2010中,输出为:

default
move
default
move
default
move
Run Code Online (Sandbox Code Playgroud)

在GCC 4.4.0(MinGW)中,( - 02 -std = c ++ 0x),输出为:

default
copy
copy
copy
Run Code Online (Sandbox Code Playgroud)

发生了什么,我该如何解决?副本对于实际类来说是昂贵的,默认构造和移动都很便宜.

c++ gcc mingw rvalue-reference c++11

22
推荐指数
2
解决办法
494
查看次数

什么是ref-qualifier`const &&`的用法?

在上一个问题之后,我一直在研究ref-qualifiers.

给出下面的代码示例;

#include <iostream>
#include <string>
#include <utility>

struct A {
  std::string abc = "abc";
  std::string& get() & {
    std::cout << "get() &" << std::endl;
    return abc;
  }
  std::string get() && {
    std::cout << "get() &&" << std::endl;
    return std::move(abc);
  }
  std::string const& get() const & {
    std::cout << "get() const &" << std::endl;
    return abc;
  }
  std::string get() const && {
    std::cout << "get() const &&" << std::endl;
    return abc;
  }
};

int main()
{
  A a1;
  a1.get();
  const …
Run Code Online (Sandbox Code Playgroud)

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

22
推荐指数
3
解决办法
4824
查看次数

可以std :: string重载"substr"为rvalue*this并窃取资源吗?

它只是发生在我身上,我注意到std::stringsubstr操作可能是右值更有效时,它可以盗取分配的内存*this.

N3225的标准库包含以下成员函数声明 std::string

basic_string substr(size_type pos = 0, size_type n = npos) const;
Run Code Online (Sandbox Code Playgroud)

可以实现substr针对rvalues 优化的实现是否会重载并提供两个版本,其中一个版本可以为rvalue字符串重用缓冲区?

basic_string substr(size_type pos = 0) &&;
basic_string substr(size_type pos, size_type n) const;
Run Code Online (Sandbox Code Playgroud)

我想rvalue版本可以实现如下,*this将设置的内存*this重用于移动状态.

basic_string substr(size_type pos = 0) && {
  basic_string __r;
  __r.__internal_share_buf(pos, __start + pos, __size - pos);
  __start = 0; // or whatever the 'empty' state is
  return __r;
}
Run Code Online (Sandbox Code Playgroud)

这是否在常见的字符串实现上以有效的方式工作,还是会占用过多的内务管理?

c++ substr rvalue-reference c++11

21
推荐指数
1
解决办法
1682
查看次数

为什么C++ 11具有值参数的隐式移动,而不是rvalue参数?

在C++ 11中,值参数(和其他值)在返回时享受隐式移动:

A func(A a) {
    return a; // uses A::A(A&&) if it exists
}
Run Code Online (Sandbox Code Playgroud)

至少在MSVC 2010中,右值参考参数需要std::move:

A func(A && a) {
    return a; // uses A::A(A const&) even if A::A(A&&) exists
}
Run Code Online (Sandbox Code Playgroud)

我认为内部函数,右值引用和值的行为类似,唯一的区别是在值的情况下,函数本身负责销毁,而对于右值引用,责任在外面.

在标准中对待它们的动机是什么?

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

21
推荐指数
3
解决办法
3688
查看次数

使用`void*`将右值引用左值引用到左值

在尝试理解右值引用的工作原理时,我最终得到了这段代码:

int* iptr = nullptr;
int*&& irr = iptr;
Run Code Online (Sandbox Code Playgroud)

编译上面的代码会出现以下错误:

错误:对'int*'类型的rvalue引用不能绑定到'int*'类型的左值

我理解这是正确的,但为什么下面的代码,我使用a void*而不是int*编译绑定,编译没有任何问题?运行时行为是正确的还是我应该期望未定义的行为?

int* iptr = nullptr;
void*&& irr = iptr;
Run Code Online (Sandbox Code Playgroud)

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

21
推荐指数
2
解决办法
1055
查看次数

为什么在C++ 0x rvalue引用的前向定义中使用identity?

Rvalue References简介中,forward定义如下:

  template <typename T>
  struct identity { typedef T type; };

  template <typename T>
  T &&forward(typename identity<T>::type &&a) { return a; }
Run Code Online (Sandbox Code Playgroud)

identity班级的目的是什么?为什么不:

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

rvalue-reference c++11

20
推荐指数
1
解决办法
653
查看次数

终身扩展和条件运算符

本地左值引用-const和rvalue引用可以延长临时值的生命周期:

const std::string& a = std::string("hello");
std::string&& b = std::string("world");
Run Code Online (Sandbox Code Playgroud)

当初始值设定项不是简单表达式,但使用条件运算符时,这是否也有效?

std::string&& c = condition ? std::string("hello") : std::string("world");
Run Code Online (Sandbox Code Playgroud)

如果其中一个结果是临时对象,但另一个结果不是?

std::string d = "hello";
const std::string& e = condition ? d : std::string("world");
Run Code Online (Sandbox Code Playgroud)

当条件为假时,C++是否要求临时扩展的生命周期?

回答有关不可复制对象的问题时出现了这个问题.

c++ object-lifetime rvalue-reference temporary-objects c++11

20
推荐指数
1
解决办法
540
查看次数

防止非常量左值解析为右值引用而不是const左值引用

我无法通过const引用重载函数来获取值,或者如果它是rvalue则是rvalue引用.问题是我的非const左值绑定到函数的右值版本.我在VC2010中这样做.

#include <iostream>
#include <vector>

using namespace std;

template <class T>
void foo(const T& t)
{cout << "void foo(const T&)" << endl;}

template <class T>
void foo(T&& t)
{cout << "void foo(T&&)" << endl;}

int main()
{
    vector<int> x;
    foo(x); // void foo(T&&) ?????
    foo(vector<int>()); // void foo(T&&)
}
Run Code Online (Sandbox Code Playgroud)

优先级似乎是推导foo(x)为

foo< vector<int> & >(vector<int>& && t)
Run Code Online (Sandbox Code Playgroud)

代替

foo< vector<int> >(const vector<int>& t)
Run Code Online (Sandbox Code Playgroud)

我尝试用r替换rvalue-reference版本

void foo(typename remove_reference<T>::type&& t)
Run Code Online (Sandbox Code Playgroud)

但这只会导致所有内容都解析为const-lvalue引用版本.

我该如何防止这种行为?为什么这仍然是默认值 - 考虑到允许修改rvalue-references似乎很危险,这给我留下了意外修改的局部变量.

编辑:刚添加了非模板版本的函数,它们按预期工作.将函数设为模板会更改重载决策规则吗?那真是令人沮丧!

void bar(const vector<int>& t)
{cout << "void bar(const …
Run Code Online (Sandbox Code Playgroud)

c++ templates metaprogramming rvalue-reference

19
推荐指数
2
解决办法
1902
查看次数

在重载函数的函数参数中使用rvalue引用会创建太多组合

想象一下,你有很多重载的方法(在C++ 11之前)看起来像这样:

class MyClass {
public:
   void f(const MyBigType& a, int id);
   void f(const MyBigType& a, string name);
   void f(const MyBigType& a, int b, int c, int d);
   // ...
};
Run Code Online (Sandbox Code Playgroud)

这个函数复制了a(MyBigType),所以我想通过提供一个版本f来移动a而不是复制它来添加优化.

我的问题是,现在f重载次数将重复:

class MyClass {
public:
   void f(const MyBigType& a, int id);
   void f(const MyBigType& a, string name);
   void f(const MyBigType& a, int b, int c, int d);
   // ...
   void f(MyBigType&& a, int id);
   void f(MyBigType&& a, string …
Run Code Online (Sandbox Code Playgroud)

c++ rvalue-reference c++11

19
推荐指数
3
解决办法
1855
查看次数

为什么这个右值引用绑定到左值?

我不明白为什么以下代码在GCC 8.0上编译:

decltype(auto) foo(int&& r) {
    return r;
}
Run Code Online (Sandbox Code Playgroud)

foo,声明类型rint&&,所以返回类型foo也是int&&.但r它本身是一个左值,而左值不能绑定到右值引用.

我错过了什么吗?

c++ decltype rvalue-reference language-lawyer c++14

19
推荐指数
1
解决办法
401
查看次数