首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >第一个C++版本中物体不能移动的技术原因?

第一个C++版本中物体不能移动的技术原因?
EN

Stack Overflow用户
提问于 2020-08-07 10:54:30
回答 3查看 188关注 0票数 0

我不是在问意见,不是关于什么更好或者什么更好,而是关于客观事实: Stroustrup或其他合作者选择强加对象不能重新定位的实际原因。

我无法找到决定不能更改对象地址的技术原因(不幸的是,任何有关移动或复制对象的搜索都会因语言后面引入的迁移/复制语义而变得混乱)。

,我的意思是:当对象被复制时,C++正确地强制构造函数(不这样做将违背OOP范式)。但是,从一开始就决定不允许将对象A从address addr1移动到addr2,除非调用了复制构造函数。这个选择背后的技术原因是什么?为什么决定它的地址对一个对象如此重要?

多态对象有一个指向它们vtable的指针,但相反的情况并非如此,因此移动对象不应该破坏vtable。因此,这肯定还有另一个原因。

此外,还有其他OOP语言可以自由地移动对象。所以,OOP范式不是原因。

也许在设计C++语言时,一些额外的编程原则被认为是不可否认的,而这些原则是禁止移动对象的?哪几个?

EN

回答 3

Stack Overflow用户

发布于 2020-08-07 12:33:39

,也许在他们设计C++语言的时候,一些额外的编程原则被认为是不可否认的,这是禁止移动对象的吗?哪几个?

那些说它应该有效地映射到硬件实现上的人,这意味着原始指针,这意味着地址-标识。

还有其他一些OOP语言,可以自由地移动对象。所以,OOP范式并不是

是的,为了垃圾收集器的方便,这些语言不介意在任何地方插入额外的间接或复杂层。这与C++的目标或多或少是对立的。

决定不允许将对象A从地址addr1移动到addr2,除非调用了副本构造函数

构造函数是不相关的,因为在C++中,所有对象(包括POD结构,甚至标量原语)都有一个标识。这个身份是(或被绑定到)他们的地址。您也不能移动int,您只能复制它。即使使用复制构造函数,也不能移动对象。实际上,即使使用移动构造函数,也不能移动对象,因为这只是一个破坏性的副本。它不会假装更改现有对象的地址。

我无法找到决定不能更改对象地址的技术原因

现在,对象的地址也不能更改。

这在隐藏或抽象原始指针的语言中是可能的。C++公开对象的原始引用和指针,因此在不破坏对对象的引用的情况下无法更改对象的地址。

如果您想要创建一个可以移动的对象,即Java运行时可以随意调整内存,则需要确保只有通过具有所需保证的智能指针才能访问该对象。由于this指针始终是实例方法中的原始指针,因此还必须确保它没有实例方法,或者您的智能指针可以同步访问,以防止调用期间的重定位。

票数 1
EN

Stack Overflow用户

发布于 2020-08-07 14:55:53

要理解C++的历史发展,您需要了解该开发的上下文。当然,C++在历史上植根于C,这不是一个随机的选择。C在历史上是非常重要的。

为了观察C的成功,我们需要将它与同时代的人进行对比。像COBOL、Algol和FORTRAN这样的语言很笨拙,而且不灵活。Lisp、Smalltalk和Modula-2等语言更优雅,但性能不佳。在C蓬勃发展的时代,性能仍然是一个非常紧迫的问题。这早在多Ghz多核CPU的时代之前就已经出现了。C几乎可以为您提供装配的性能,具有更高的可移植性和更低的开发成本。

但是如前所述,C缺乏一些在开发更大的程序时真正相关的特性。即使是在C的原始家,这也是他们自己的产品中所提到的。AT&T以一种面向对象的方式开发了他们的电话交换机(5 5ESS),但使用了自己的C语言。在这种情况下,C++非常有意义。编译器技术的改进使我们能够以比手工操作更低的成本获得OO的好处。字符串类型不需要非常昂贵,而且它比C的strcpy更容易使用。

现在,C++需要形式化对象的工作方式,这是一个非常早期的决定--这是导致C语言的关键开发。事实上,C++重新定义了C语言,使得许多C程序也是正确的C++程序,而来自C的struct变成了C++中的对象类型。

现在我们来谈谈你的“行动”问题。在C中,您可以使用memcpy结构。这将打破更复杂的类型,如字符串。即使是C语言中的char*也是脆弱的。C++解决方案是复制器和赋值操作符。这些发明使得C++比C++更安全,并且允许更多有用的数据结构。但是这里的决定定义了C++对象是如何工作的。C structs在默认情况下保持不变,C++对象也一样,因为否则C程序将不是有效的C++程序。

票数 1
EN

Stack Overflow用户

发布于 2020-08-07 18:35:54

我将重新表述这个问题,因为我理解它的本质,然后回答它。

为什么必须通过调用构造函数和析构函数来重新分配对象数组?为什么我们不能将旧对象的字节复制到一个新地址并完成它呢?

重申一下,我对OP术语的理解是将对象的字节复制到新对象(如果保证不再使用原始对象的话)。它与C++移动语义无关。

复制字节并不能保证对象的完整性,原因有几点。

  1. 实现可以自由地使用隐藏的内部指针来表示对象。使用多重继承的对象通常以这种方式表示。将字节复制到新位置会使这些指针无效。在这种情况下复制字节会使这些指针无效,并破坏object.
  2. Programmers的完整性,也可以自由使用内部指针。对象可以包含指向它自己的子对象的指针。对象还可以指向依赖对象,这些对象可以指向它们的所有者。在这种情况下复制字节会使这些指针无效,并破坏对象的完整性。

当然,对于C对象,第二个要点也是正确的。但在C语言中,也不能简单地分配这样的对象。需要更新内部指针。

在C++中,赋值总是有效的(很好,用户编写了正确的复制构造函数和赋值操作符)。如果分配总是正常工作,并且中断某些数组的重新分配,这是不合理的。所以这件事还没完成。

注意,如果C+编译器能够证明它不会改变程序的语义,那么它允许字节复制对象而不是复制构造它们。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63300372

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档