自从我第一次看到它所处的位置以来,我有了疑虑,但是现在我看到了一些代码(中等初学者),它让我感到不仅仅是丑陋,而且可能很慢?
如果struct S
内有class A
,class B
(作文),我需要做类似的事情:
struct S { int x[3] {1, 2, 3}; };
S *s;
A(): s {new S} {}
B(A *a) { a->s->x[1] = 4; }
这条链的效率如何:a->s->x[1]
?这是丑陋和不必要的吗?潜在的阻力?如果链条中的级别更高,那会更加丑陋吗?这应该避免吗?或者,如果不是以前的任何一个机会,这是一个比以下更好的方法:
S s;
B(A *a): { a->s.x[1] = 4; }
似乎这样慢,因为(如果我做对了)我必须复制struct
,而不是使用指向它的指针。我不知道该怎么想。
答案 0 :(得分:2)
在许多迭代中使用指针到对象的实际成本不一定是指针本身的解除引用,而是将另一个缓存帧加载到CPU缓存中的潜在成本。只要指针指向当前加载的缓存帧内的某些内容,成本就会降低。
答案 1 :(得分:2)
这是一种更好的方法
如果您刚刚拒绝,则完全没有。
首先,在现代C ++中,你应该避免使用所有权的原始指针,这意味着你不应该使用new
。使用符合您需求的智能指针之一:
std::unique_ptr
获得独家所有权。std::shared_ptr
用于多个对象 - >相同的资源。我无法准确地告诉您有关性能的信息,但通过成员s
的直接访问速度不会比通过解除引用的成员s
直接访问速度慢。你应该总是在这里寻找非指针方式。
但又退一步了。你首先不需要指针。 s
应该只是第二个例子中的对象,并替换B
的构造函数中的指针作为参考。
我必须复制结构,而不是使用 指向它的指针。
不,不会复制。
答案 2 :(得分:0)
始终尽可能避免使用new进行动态分配,因为这可能是一项非常昂贵的操作,并且需要间接操作来访问您分配的内容。如果你使用它,你也应该使用智能指针,但在你的情况下,绝对没有理由这样做 - 只需在你的类中有一个S(值,而不是指针)的实例。
答案 3 :(得分:0)
如果你认为a->s->x[1] = 4
是丑陋的,那么它是因为链而不是因为箭头,而a->s.x[1] = 4
在相同程度上是丑陋的。在我看来,代码暴露S
超过必要的,尽管有时可能存在这样做的充分理由。
性能是重要的一点,其他是可维护性和适应性。成员访问链通常支持信息隐藏的原则,其程度小于避免这种链的设计;涉及的对象(以及所涉及的代码)比其他方式更紧密耦合,这通常会带来可维护性的代价(例如,Law of Demeter作为更好的信息隐藏的设计原则:
特别是,对象应该避免调用成员的方法 另一个方法返回的对象。对于许多现代面向对象 使用点作为字段标识符的语言,可以说明法律 简单地说“只使用一个点”。也就是说,代码a.b.Method()中断了 a.Method()没有的法律。作为一个类比,当一个人想要一只狗 走路时,一个人不会指挥狗的腿直接行走;代替 一个命令狗然后命令它自己的腿。
例如,假设您将数组x
的大小从3更改为2,那么您不仅要查看类A
的代码,还要查看其他任何类的代码。你的计划。
但是,如果我们避免暴露大部分组件S
,则类A
可以由成员/运算符int setSAt(int x, int value)
扩展,然后可以检查例如数组边界;更改S
只影响那些S
作为组件的类:
B(A *a) { a->setSAt(1,4); }