gpt4 book ai didi

c++ - int vs const int&

转载 作者:IT老高 更新时间:2023-10-28 13:23:27 26 4
gpt4 key购买 nike

关闭。这个问题是opinion-based .它目前不接受答案。












想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题.

10 个月前关闭。




Improve this question




我注意到我通常使用常量引用作为返回值或参数。我认为原因是它的工作原理与在代码中使用非引用几乎相同。但它肯定需要更多空间并且函数声明变得更长。我可以接受这样的代码,但我认为有些人认为这是一种糟糕的编程风格。

你怎么看?在 int 上写 const int& 值得吗?我认为它无论如何都是由编译器优化的,所以也许我只是在浪费时间编码它,一个?

最佳答案

在 C++ 中,我认为使用 const T& 的反模式很常见。就像一个聪明的方式只是说 T在处理参数时。然而,值和引用(无论是否为常量)是两个完全不同的东西,总是盲目地使用引用而不是值会导致微妙的错误。
原因是在处理引用时,您必须考虑两个不存在于值中的问题:生命周期别名 .
举个例子,应用这种反模式的地方是标准库本身,其中 std::vector<T>::push_back接受参数 a const T&而不是一个值,这可以在代码中反咬一口,例如:

std::vector<T> v;
...
if (v.size())
v.push_back(v[0]); // Add first element also as last element
此代码是一个定时炸弹,因为 std::vector::push_back想要一个 const 引用,但执行 push_back 可能需要重新分配,如果发生这种情况,则意味着在重新分配后,收到的引用将不再有效( 生命周期 问题)并且您进入未定义行为领域¹。
从逻辑的角度来看,更好的是接受一个值(即 void std::vector<T>::push_back(T x) ),然后在容器内的最终位置有效地移动该值。那么调用者最终可能会使用 std::move如果这被认为很重要。
别名 如果使用 const 引用而不是值,则问题反而是微妙问题的根源。例如,我被这种代码咬过:
struct P2d
{
double x, y;
P2d(double x, double y) : x(x), y(y) {}
P2d& operator+=(const P2d& p) { x+=p.x; y+=p.y; return *this; }
P2d& operator-=(const P2d& p) { x-=p.x; y-=p.y; return *this; }
};

struct Rect
{
P2d tl, br;
Rect(const P2d& tl, const P2d& br) : tl(tl), bt(br) {}
Rect& operator+=(const P2d& p) { tl+=p; br+=p; return *this; }
Rect& operator-=(const P2d& p) { tl-=p; br-=p; return *this; }
};
该代码乍一看似乎很安全, P2d是一个二维点, Rect是一个矩形,加/减一个点意味着平移这个矩形。
然而,如果要将矩形平移回原点,您可以写 myrect -= myrect.tl;代码将不起作用,因为翻译运算符已被定义为接受(在这种情况下)引用同一实例的成员的引用。
这意味着在用 tl -= p; 更新左上角之后左上角将是 (0, 0)理所当然,但也 p同时会变成 (0, 0)因为 p只是对左上角成员的引用,因此右下角的更新将不起作用,因为它将通过 (0, 0) 进行翻译因此基本上什么都不做。
请不要因为 const这个词而误以为const引用就像一个值。 .如果您尝试使用该引用更改被引用的对象,该词的存在只是为了给您编译错误,但并不意味着被引用的对象是常量。更具体地说,const ref 引用的对象可能会更改(例如,由于别名),甚至在您使用它时可能会消失(生命周期问题)。
const T& const 表示引用的属性,而不是被引用对象的属性:它是无法使用它来更改对象的属性。大概 只读 将是一个更好的名字 const IMO 有一种心理效应,即在您使用引用时插入对象将保持不变的想法。
您当然可以通过使用引用而不是复制值来获得令人印象深刻的加速,尤其是对于大类。但是在使用引用时,您应该始终考虑别名和生命周期问题,因为实际上它们只是指向其他数据的指针。
然而,对于“原生”数据类型(整数、 double 、指针),引用实际上会比值慢,并且使用它们代替值没有任何好处。
此外,const 引用始终意味着优化器的问题,因为编译器被迫偏执,并且每次执行任何未知代码时,它都必须假设所有引用的对象现在可能具有不同的值( const 对于引用意味着绝对没有对于优化器;这个词只是为了帮助程序员 - 我个人不太确定它有多大帮助,但那是另一个故事)。

(1) 显然 ( https://stackoverflow.com/a/18794634/320726 ) 标准说这种情况是有效的,但即使有这种解释(我完全不同意),问题仍然普遍存在。 push_back不在乎 身份的对象,因此应该按值获取参数。当您将 const 引用作为值传递给函数时,您有责任确保引用的对象在函数的整个持续时间内保持事件状态。与 v.push_back(v[0])如果没有进行预订,这只是错误的,如果发生这种情况,IMO(给定 push_back 签名)是调用者的错。然而,真正的逻辑错误是 push_back界面设计(有意为之,在效率的祭坛上牺牲了逻辑正确性)。不确定是不是因为那个缺陷报告,但我看到一些编译器在这种特殊情况下“修复”了这个问题(即 push_back 会检查被推送的元素是否来自 vector 本身)。

关于c++ - int vs const int&,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4705593/

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