gpt4 book ai didi

c++ - 未实现的拷贝构造函数的拷贝赋值

转载 作者:行者123 更新时间:2023-11-30 03:04:51 25 4
gpt4 key购买 nike

#include "stdafx.h"

class Base
{
public:
Base(){}
virtual ~Base(){}
private:
Base(const Base &other) ; // Only declaration! No definition.
Base &operator=(const Base &other);
} ;

int _tmain(int argc, _TCHAR* argv[])
{
const Base b ; // ok
const Base *pb = &Base() ; // ok
const Base &qb = Base() ; // Illegal, why?

return 0;
}

然后,看下面的代码:

#include "stdafx.h"

class Base
{
public:
Base(){}
virtual ~Base(){}
public:
Base(const Base &other) ; // Only declaration! No definition.
Base &operator=(const Base &other);
} ;

int _tmain(int argc, _TCHAR* argv[])
{
const Base b ; // ok
const Base *pb = &Base() ; // ok
const Base &qb = Base() ; // It's ok! why?

return 0;
}

最佳答案

忽略 const *Base = &Base(); 获取临时地址,在大多数情况下会导致未定义行为,因为在表达式末尾临时将是销毁并且指针的任何取消引用都是 UB

当您尝试将常量引用绑定(bind)到临时变量时,该语言声明该操作(在语义上)是将临时变量复制到未命名的变量,然后将引用绑定(bind)到该变量。

const type& r = f();    // where f() returns a type (not a reference)

相当于:

const type __tmp = f(); // __tmp variable created by the compiler
const type& r = __tmp;

这解释了为什么在第一种情况下,因为复制构造函数不可访问,所以不允许编译器创建 __tmp 变量(const type __tmp = f() 编译失败)并告诉你。

现在标准允许编译器省略变量的拷贝,特别是在那一行中,允许编译器放置 __tmpf() 的结果在内存中完全相同的位置 1 并避免执行复制。在第二种情况下,编译器已检查是否允许复制(复制构造函数可用),但已优化复制,因此它不会调用该函数。

为什么没有定义构造函数就认为是可用的呢?好吧,这是单独编译模型的一部分,编译器在决定构造函数是否有效时,只检查当前的翻译单元,它不知道复制构造函数是否在不同的 TU 中可用.因为省略了拷贝,所以不会在二进制文件中调用复制构造函数,并且链接器不需要解析该符号,因此可以正常编译和链接。


1有关更多详细信息,并且在标准范围之外,大多数编译器(据我所知)实现按大对象(不适合寄存器的对象)的值返回通过传递一个指向函数的隐藏指针,调用者在本地堆栈中为 __tmp 保留空间,并将该指针传递给 f()。使用此调用约定,在这种情况下返回的对象根本不存在,即使调用未用于初始化新对象也是如此。

在示例中的情况下,返回的类型适合寄存器,许多编译器会在返回之前将结果值存储在寄存器中。这是必须执行复制(概念上)的确切情况,因为您不能将引用绑定(bind)到寄存器,但再次省略了对复制构造函数的调用,并且编译器只是将 register 存储在 __tmp 的位置。

关于c++ - 未实现的拷贝构造函数的拷贝赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8309065/

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