gpt4 book ai didi

C++ 风格 : use parameter or member in constructor body

转载 作者:搜寻专家 更新时间:2023-10-31 00:18:13 25 4
gpt4 key购买 nike

这是我经常遇到的问题,最后想听听大家对自己喜欢的风格的看法。

在构造函数中使用参数或成员(用于只读目的)是更好/首选的做法吗?例如,在这个简单的 vector 类中:

#include <iostream>
#include <array>

class SimpleDoubleVector {
private:
double * _data;
std::size_t _size;
public:
SimpleDoubleVector(double * data, std::size_t size) :
_size(size) {
_data = new double[size];
for (int k=0; k<size; ++k)
_data[k] = data[k];
}
~SimpleDoubleVector() {
delete[] _data;
}
};

是不是更好

  1. 在整个构造函数中使用size(如图所示)
  2. 先赋值/初始化_size,再使用_size

可能的后果:

哪个更具可读性?

哪个会提供更好的性能(或者由于 copy propagation 而它们是等价的)?直觉上,感觉从参数中读取会更有效率,因为它永远不会被写入,因此会导致更简单的 dependency graph。 .

我知道这可能看起来很迂腐,但它经常出现,我真的很想剖析最好的方法(或者至少更好地理解利弊)。

最佳答案

语义上,局部变量(以及参数)通常优于成员变量。以这个有点捏造的例子为例:

class Complex {
float real_;
float imag_;

public:
Complex& operator*=(const Complex& that) {
real_ = real_ * that.real_ - imag_ * that.imag_;
imag_ = imag_ * that.real_ + real_ * that.imag_;
}
};

乍一看不错,直到您意识到第一行中对 real_ 的修改更改了第二行中 real_ 的值。即使您捕获了它并将原始的 real_ 存储在局部变量中,您也可能遇到 c *= c 的情况,其中左侧和右侧- 运算符(operator)的手边是别名,并且您在第一行中更改 real_ 无意中更改了第二行中的 that.real_。换句话说,对成员变量的更改能够导致对局部变量的更改不会产生的副作用。

在速度方面,任何合理的编译器都会发现两者相同。如果您重用该参数,不合理的编译器可能会产生更好的代码,因为它已经在本地并且编译器肯定知道除了它可以看到的代码之外没有任何东西可以改变该值。同样值得注意的是,稍微复杂的情况,即使是在好的编译器上,也会为这样的情况产生更糟糕的输出:

void MyClass::foo(int value, MyClass* child) {
value_ = value;
for (int i = 0; i < value_; ++i) {
if (child) child->value_ = i;
bar(i, child);
}
}

这个函数完全没有办法保证thischild是不同的指针。所以它不能在循环迭代之间将 value_ 保存在寄存器中,因为对 child->value_ 的赋值可能已经改变了 this->value_。在这种情况下,即使是优秀的编译器也会希望看到您使用该参数。

在可读性方面,如果您认为成员(member)名称前后的下划线(或 m_,就此而言)使其不可读,那么您为什么要使用那个符号?构造函数体和普通函数体之间的一致性绝对是可取的。所以我会争辩说,如果你的语义鼓励在函数的持续时间内将成员变量拉入局部变量,那么也在构造函数中这样做(只需使用参数)。但是,如果在您的其他成员函数中没有使用这样的约定,那么也不要在构造函数中这样做——让编译器来处理它。

关于C++ 风格 : use parameter or member in constructor body,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11219101/

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