标签: rvalue

C++中的引用和文字

我知道"文字"(c字符串,int或其他)存储在某处(在一个只读数据部分显然是.rodata)也许这不准确......

我想了解为什么此代码导致运行时错误:

#include <iostream>
using namespace std;

const int& foo()
{
    return 2;
}
const char* bar()
{
    return "Hello !";
}

int main() {

    cout << foo() << endl; // crash

    cout << bar() << endl; // OK

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

foo返回一个文字的const引用(2)为什么会导致崩溃?是存储在foo()堆栈中的整数2?

另请参阅:为什么字符串文字是l值而所有其他文字都是r值?

c++ rvalue

3
推荐指数
1
解决办法
399
查看次数

为什么内置赋值在 C++ 中返回非常量引用而不是常量引用?

(注意原来的问题标题有“而不是右值”而不是“而不是常量引用”。下面的答案之一是对旧标题的回应。为了清楚起见,这是固定的)

C 和 C++ 中的一种常见构造是用于链式赋值,例如

    int j, k;
    j = k = 1;
Run Code Online (Sandbox Code Playgroud)

第二=首先进行,用该表达k=1具有副作用k被设置为1,而表达式本身的值是1。

但是,在 C++ 中合法(但在 C 中不合法)的一种构造如下,它对所有基本类型都有效:

    int j, k=2;
    (j=k) = 1;
Run Code Online (Sandbox Code Playgroud)

在这里,表达式j=k具有设置j为 2的副作用,并且表达式本身成为对 的引用j,然后将其设置j为 1。据我所知,这是因为表达式j=k返回- const int&,例如一般来说是左值。

通常也建议将此约定用于用户定义的类型,如Meyers Effective C++中的“Item 10: Have assignment operators return a (non-const) reference to *this”中所述。本书的这一部分并没有试图解释为什么参考文献是非引用的const,甚至没有注意到const顺便提及的非引用性。

当然,这当然增加了功能,但(j=k) = 1;至少可以说这种说法似乎很尴尬。

如果约定改为使用内置赋值返回const引用,那么自定义类也将使用此约定,并且 C 中允许的原始链式构造仍然有效,无需任何无关的副本或移动。例如,以下正确运行:

#include …
Run Code Online (Sandbox Code Playgroud)

c++ return-type rvalue lvalue assignment-operator

3
推荐指数
1
解决办法
574
查看次数

除了写入临时值没有效果之外,为什么右值不能绑定到非常量左值引用?

我在这里阅读了SO问题并理解了答案的这一部分:“但是如果你将一个临时值绑定到一个非常量引用,你可以继续“永远”传递它,只是为了让你对对象的操作消失,因为在某个地方一路上你完全忘记了这只是暂时的。”

也就是说,在以下内容中:

#include <iostream>

void modifyValue(int& rValue) {
    rValue++;
}

int main() {
    modifyValue(9899);

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

如果右值可以绑定到非常量左值引用,那么可能会进行许多修改,这些修改最终会被丢弃(因为右值是临时的),这是无用的。

然而,这似乎定义良好(写入临时值就像写入任何值一样,生命周期与写入的有效性无关)。

这是禁止指定绑定的完全正确的理由(即使绑定将被明确定义),但是一旦我认为禁止这种绑定会强制需要转发引用,我的问题就开始形成。

是否还有其他原因(即,除了写入临时值之外)为什么右值无法绑定到非常量左值引用?

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

3
推荐指数
1
解决办法
2080
查看次数

传递const int *和int *时,将调用不同版本的重载函数(const int * const&/ &amp;&amp;)

我在代码中遇到了一个错误,该错误正在调用错误的重载函数。

问题归结为:

void func(const int* const& ptr){
    std::cout << "LValue reference\n";
}
void func(const int* const&& ptr){
    std::cout << "RValue reference\n";
}

int main(){
    const int* ptr;

    func(ptr);

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

上面的代码按预期工作,它打印LValue reference。但是,当我改变const int* ptrint* ptr,该程序打印RValue reference。这对我来说很奇怪,因为我通过了一个确认的LValue。这使我相信正在发生某种隐式转换,从而将其转换为RValue。我确实使用godbolt编译器资源管理器进行了研究,乍看之下它会证实我的怀疑,但是我对汇编一无所知,因此无法确定。

所以问题是:这里发生了什么?

c++ pass-by-reference rvalue lvalue implicit-conversion

3
推荐指数
1
解决办法
56
查看次数

有没有办法在提供左值和右值重载的同时删除重复代码?

在学习 C++ 时,我决定编写一个简单的模板化二叉搜索树 (bst) 并遇到以下问题:我希望能够通过传递左值和右值来构造一个 bst 。同样,我希望能够插入左值和右值。所以我最终得到了很多我不喜欢的重复代码:const T &valT &&val

/// copy constructor
explicit inline constexpr binary_search_tree(const T &val)
    : _root{std::make_unique<binary_search_tree_node>(val)} {}

/// move constructor
explicit inline constexpr binary_search_tree(T &&val)
    : _root{std::make_unique<binary_search_tree_node>(std::move(val))} {}
Run Code Online (Sandbox Code Playgroud)

对于构造函数, wherebinary_search_tree_node是其私有成员binary_search_tree,然后还必须提供复制和移动构造函数:

struct binary_search_tree_node {
  T value;
  std::unique_ptr<binary_search_tree_node> left;
  std::unique_ptr<binary_search_tree_node> right;

  // prohibit creation of tree_node without value
  inline constexpr binary_search_tree_node() = delete;

  /// copy constructor
  explicit inline constexpr binary_search_tree_node(const T &val)
      : value{val}, left{nullptr}, right{nullptr} {} …
Run Code Online (Sandbox Code Playgroud)

c++ overloading code-duplication rvalue lvalue

3
推荐指数
1
解决办法
234
查看次数

完美转发解释为右值引用

我的理解是这ConcreteType&&是一个右值并且TemplateType&&是“完美转发”。

我正在尝试使用完美转发,但 clang-tidy 将其解释为右值引用。

clang 和 gcc 不会抱怨,但在进行任何进一步分析之前,clang-tidy 将其标记为解析错误,所以我不确定这是代码问题还是 clang-tidy 问题。

我怀疑这与我在构造函数中使用它有关,但我不确定。

最低代码:

#include <memory>

template <typename T>
class my_wrapper {
  T val;

 public:
  my_wrapper(T&& val_)
      : val{std::forward<T>(val_)} {}
};


struct my_struct {
  int x;
};

auto xyz() {
  my_struct ms{3};
  return my_wrapper<my_struct>(ms);
}
Run Code Online (Sandbox Code Playgroud)

错误信息:

Error while processing /path/foo.cpp.
/path/foo.cpp:20:25: error: no matching constructor for initialization of 'my_wrapper<my_struct>' [clang-diagnostic-error]
  my_wrapper<my_struct> wrap(ms);
                        ^
/path/foo.cpp:5:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from …
Run Code Online (Sandbox Code Playgroud)

c++ rvalue perfect-forwarding clang-tidy

3
推荐指数
1
解决办法
62
查看次数

如何理解 void (*&amp;&amp;)() 函数

我使用C++ https://cppinsights.io/查看实例化的进度,Function&&和Function之间有一些令人困惑的地方。

我评论了cppinsights生成的代码。

template<typename Function>
void bind(int type, Function&& func)
{
}

/*
// instantiated from the function above:  
template<>
inline void bind<void (*)()>(int type, void (*&&)() func)
{
}
*/

template<typename Function>
void bindtwo(int type, Function func)
{
}

/*
template<>
inline void bindtwo<void (*)()>(int type, void (*func)())
{
}
*/

void test()
{
    std::cout << "test" << std::endl;
}

int main()
{
    bind(1, &test);
    bindtwo(2, test);
}
Run Code Online (Sandbox Code Playgroud)

c++ rvalue rvalue-reference

3
推荐指数
1
解决办法
242
查看次数

数组或函数左值是否可以转换为右值?

根据C++标准2003:

An lvalue (3.10) of a non-function, non-array type T can be converted to an rvalue.
Run Code Online (Sandbox Code Playgroud)

数组和函数不能转换为rvalue是什么意思?

c++ rvalue

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

C++ 11 - 返回由左值传递给函数的rvalue?

C++ 11中,通常的做法是通过引用将左值传递给函数.

int& f(int& a){
    return a;
}

int main(void){
    auto a = 1;
    auto b = f(a);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,是否可以通过右值引用将值传递给函数并通过lvalue返回此值?

int& f(int&& a){
    return a;
}

int main(void){
    auto b = f(1);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它为什么或为什么不可能?

c++ return rvalue lvalue rvalue-reference

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

用于左值和右值的C++运算符重载[]

我创建了一个包含整数数组的类Array.从main函数,我正在尝试使用[]获取Array中的数组元素,就像在main中声明的数组一样.我重载了运算符[],如下面的代码所示; 第一个函数返回一个左值,第二个函数返回一个右值(未显示构造函数和其他成员函数.)

#include <iostream>
using namespace std;

class Array {
public:
   int& operator[] (const int index)
   {
      return a[index];
   }
   int operator[] (const int index) const
   {
      return a[index];
   }

private:
   int* a;
}
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试从main调用这两个函数时,即使变量未用作左值,也只访问第一个函数.如果可以通过使用左值函数来处理所有事情,我无法看到为rvalue创建单独函数的重点.

以下代码是我使用的主要功能(Operator <<适当重载.):

#include "array.h"
#include <iostream>
using namespace std;

int main() {
   Array array;
   array[3] = 5;                // lvalue function called
   cout << array[3] << endl;    // lvalue function called
   array[4] = array[3]          // lvalue function called for both
}
Run Code Online (Sandbox Code Playgroud)

有什么方法可以调用右值函数吗?是否还需要为左值和右值定义函数?

c++ overloading rvalue lvalue operator-keyword

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