【问题标题】:Lvalue-to-rvalue conversion for class types: is there copying involved?类类型的左值到右值转换:是否涉及复制?
【发布时间】:2018-01-29 02:13:06
【问题描述】:

(我之前问过这个问题,但没有给出一个可行的例子,所以我删除了前一个。我希望在这个问题上我得到了正确的例子。)

案例:

#include <iostream>

struct S
{
    S() = default;

    S(const S &)
    {
        std::cout << "Copying" << std::endl;
    }

    S& operator=(const S &)
    {
        std::cout << "Copy assignment" << std::endl;
        return *this;
    }
};

int main()
{
    S s{};
    S s2{};
    S &ref = s;
    ref = s2;
}

据我了解,ref = s2; 包括 l2r 转换,因为它是每个 cppreference 期望的“内置直接赋值”,并且右值作为其正确参数。

我已经阅读了一些关于左值到右值转换的 SO 问题,但我仍然不确定它是否涉及对象的复制,如果涉及,它是什么类型的复制。

假设我们正在讨论类类型。

来自 [conv.lval]/2:

否则,如果 T 具有类类型,则转换会从泛左值复制初始化 T 类型的临时值,并且转换的结果是临时值的纯右值。

因此,作为左值到右值转换的一部分,涉及到复制初始化。

ref = s2; 为例,使用用户定义的复制构造函数,例如prints 'Copying',在上述语句的执行过程中会打印出'Copying'吗?

嗯,显然不会。但这意味着我在这里误解了一些东西。

左值到右值转换期间的复制初始化是不是类似于普通的 memcpy,而不是完全意义上的复制初始化?

这一切是如何运作的? :)

【问题讨论】:

  • 标准不是学习C++的好方法。我会推荐one of the books。在这种情况下,ref = s2 不会调用副本 构造函数,而是调用副本 赋值运算符
  • 从标准中学习 C++ 有点像通过阅读关于反向公司合并的法庭诉讼程序以及在知识产权讨论中的作用来学习法律。它可能会为您提供一些您需要的核心概念,但它会让您感到困惑,并且有时会过于关注当前与您的品味无关的细节。
  • @Barry 好吧,我已经阅读了几乎所有的 Meyers 和一些 Sutter :) 以及关于 l2r 的十几个 SO 问题 :) 在某些情况下它并没有让事情变得更容易,所以 is 需要达到标准 :) 我知道复制赋值运算符被调用,是的,我已经更新了示例:请注意,我有一个 ref 接受复制赋值运算符,但是 l2r似乎仍然适用;该 l2r 是否执行引用中所写的复制初始化?除非你有一整包 SO 代表,否则每个人都认为你对 lang 一无所知,这有点令人不安:(
  • @ledonter 叹了口气。我正在努力帮助你。如果您想从我的评论中推断出它来自恶意,并且仅基于您在本网站上的声誉而带有贬义,那完全取决于您。

标签: c++ c++14 copy-constructor lvalue-to-rvalue value-categories


【解决方案1】:

据我了解,ref = s2;包括 l2r 转换,因为它是每个 cppreference 期望的“内置直接分配”,并且右值作为其正确的参数。

你的错误是在这里解释赋值运算符是一个内置的。它不是。唯一具有内置赋值运算符的类型是基本类型(指针、charint 等)。您拥有的是类类型,它具有重载的赋值运算符(无论是用户提供的还是隐式的)由编译器生成)。

ref = s2; 只是调用S::operator=(S const&amp;)。它的行为就像您刚刚输入了ref.operator=(s2)。在该函数的实现中没有左值到右值的转换,因此不会制作其他副本。所发生的只是该行被打印出来。无需额外的拷贝初始化等。

如果你以不同的方式实现你的赋值运算符,如:

S& operator=(S /* no ref */) { return *this; }

然后会发生左值到右值的转换,以便实际调用此函数,您会看到复制构造函数被调用。

【讨论】:

  • “它的行为就像你刚刚输入了ref.operator=(s2),确切地说,除了评估顺序之外
猜你喜欢
  • 2020-07-14
  • 1970-01-01
  • 2017-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
  • 2014-01-17
相关资源
最近更新 更多