gpt4 book ai didi

c++ - 返回常量对象并将其分配给非常量对象

转载 作者:可可西里 更新时间:2023-11-01 18:29:16 26 4
gpt4 key购买 nike

我发现一段代码的奇怪行为显然忽略了 const-ness:

#include <iostream>

using std::cerr;

class A
{
public:
A() { cerr << "A::A()\n"; }
A(const A &a) { cerr << "A::A(const A&)\n"; }
A(A &&) { cerr << "A::A(A&&)\n"; }
A & operator = (const A &a) { cerr << "A::operator=(const A&)\n"; return *this; }
A & operator = (A &&a) { cerr << "A::operator(A&&)\n"; return *this; }
~A() { cerr << "A::~A()\n"; }

const A get() const { cerr << "const A A::get() const\n"; return A(); }
A get() { cerr << "A A::get()\n"; return A(); }
};

int main()
{
const A a;
A b = a.get();
}

首先,我在这里确实期望:a 是一个常量,因此调用 get() 的常量版本。接下来返回常量对象,但是左边是非常量对象b,所以应该调用拷贝构造函数。哪个不是:

A::A()
const A A::get() const
A::A()
A::~A()
A::~A()

这种行为是 C++ 标准所期望的吗? 那么,临时对象的常量性是否可以被 RVO 简单地忽略?以及如何在此处强制执行复制?

禁用复制省略的输出 (-fno-elide-constructors) 进行额外的移动和预期的复制构造函数调用:

A::A()
const A A::light_copy() const
A::A()
A::A(A&&)
A::~A()
A::A(const A&)
A::~A()
A::~A()
A::~A()

如果a对象不是常量,那么就是两步不复制,这也是意料之中的。

附言。这种行为对我来说很重要,因为我看到的行为打破了浅拷贝常量严格性:对于 get() 的常量版本(实际上是 shallow_copy())我需要确保不会对返回的对象进行修改,因为返回的对象是浅拷贝,对浅拷贝的修改会影响“父”对象(可能是常量)。

最佳答案

So, is it okay that constness of a temporary object is simply ignored by RVO?

是的。 [class.copy]/p31(引用 N4527,其中包含一些阐明意图的 DR;强调我的):

This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

  • in a return statement in a function with a class return type, when the expression is the name of a nonvolatile automatic object (other than a function parameter or a variable introduced by the exception-declaration of a handler (15.3)) with the same type (ignoring cv-qualification) as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value
  • [...]
  • when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same type (ignoring cv-qualification), the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move
  • [...]

第三点适用于此;请注意,类似的规则也适用于 NRVO(第一个项目符号)。

关于c++ - 返回常量对象并将其分配给非常量对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32370434/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com