Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 复制构造函数的“尝试引用已删除的函数”_C++_Copy Constructor_Rule Of Three - Fatal编程技术网

C++ 复制构造函数的“尝试引用已删除的函数”

C++ 复制构造函数的“尝试引用已删除的函数”,c++,copy-constructor,rule-of-three,C++,Copy Constructor,Rule Of Three,我正在努力使我的头脑明白5的规则 我有一个Renderable类,它定义了一个自定义析构函数,因此它似乎是5规则的一个很好的候选者。这个类在其构造函数中创建了一些资源,所以我的第一个想法是应该防止复制: class Renderable { public: Renderable(const Sprite&) { // Allocate resources } ~Renderable() { // Free resources

我正在努力使我的头脑明白5的规则

我有一个Renderable类,它定义了一个自定义析构函数,因此它似乎是5规则的一个很好的候选者。这个类在其构造函数中创建了一些资源,所以我的第一个想法是应该防止复制:

class Renderable {

public:

    Renderable(const Sprite&) {
        // Allocate resources
    }

    ~Renderable() {
        // Free resources
    }

    // Prevent copying
    Renderable(const Renderable& other) = delete;

}
我还有另一个类Unit,它在其构造函数的初始值设定项列表中创建一个Renderable:

class Unit {

public:

    Unit(const Sprite& sprite) :
            renderable(Renderable(sprite)) {}

private:

    Renderable renderable;

}
我希望这会调用常规的可渲染构造函数,但我得到的却是错误:

Renderable::Renderableconst Renderable&':尝试引用已删除的函数

为什么要调用复制构造函数

我甚至尝试向复制构造函数添加调试行,但没有打印任何内容:

Renderable(const Renderable& other) : sprite(other.sprite) {
    std::cout << "copy constructor";
}
首先,Renderablesprite创建一个可渲染的。然后尝试用该可渲染对象构造可渲染对象。从概念上讲,除了复制构造函数,它还能用什么呢

为什么要创建Renderable来初始化Renderable?这一步是不需要的,也不会起作用,因为您没有复制构造函数。您已经明确说过,您不希望代码在概念上使用复制构造函数来工作

为什么要调用复制构造函数

因为

  renderable(Renderable(sprite)) {}
这将构造一个临时可渲染对象,然后使用它来构造可渲染类成员。那将是一个巨大的挑战

我甚至尝试在复制构造函数中添加调试行,但都没有成功 印刷品:


这是因为这是允许编译器执行复制省略的情况之一。即使编译器优化了临时+复制构造,构造函数也必须仍然存在。类的某些内容会导致删除默认的复制构造函数。这可能有几个原因,但是你没有提供足够的关于你的班级的信息来确定原因是什么。

除了其他人所说的,我认为你的意思是:

Unit::Unit(const Sprite& sprite) :
    renderable(sprite) {}
这将调用转换构造函数Renderableconst Sprite&直接初始化renderable,不涉及复制


我们能得到一个吗?因为你显式调用复制构造函数的方式可以省略它,但只有在它没有被删除的情况下…@chrisdd保证复制省略即使移动和复制操作符被删除也能工作:Unit::Unitconst Sprite&Sprite:renderablesprite{}会工作吗?@NathanOliver:在那个例子中,你会得到一个默认的移动构造函数,与OP的代码相比,没有用户定义的析构函数,那么除了复制构造函数之外,还能用什么呢?C++17的保证副本省略说直接构造函数:我想我应该澄清我的意思是在概念上,而不是在实际执行中,甚至在概念上。您有一个prvalue,它实际上并没有创建临时值。@NathanOliver可能他们使用的是C++17之前的版本compiler@Dan要提供给renderable的构造函数的值是sprite。由于这是一个初始化列表,因此它是一个给定的对象,您正在构造您正在初始化的对象。它被显式删除:Renderableconst Renderable&other=delete@TEDLYNGOM在C++17中无关紧要:@NathanOliver它是对类的某些内容的注释,导致删除默认的复制构造函数。但也许我误解了。@TedLyngmo当我添加调试行时,复制构造函数没有被删除。@Dan没有,但是你也没有得到关于被删除的复制构造函数的错误。编译器发现它实际上可以同时省略复制,这就是为什么您没有看到复制构造函数消息的原因。这完全正确,谢谢。我不知道这会隐式调用可渲染构造函数。