Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++;课程:一个';重置';移动构造函数中的模板字段?_C++_Templates_Constructor_Move Semantics_Move Constructor - Fatal编程技术网

C++ C++;课程:一个';重置';移动构造函数中的模板字段?

C++ C++;课程:一个';重置';移动构造函数中的模板字段?,c++,templates,constructor,move-semantics,move-constructor,C++,Templates,Constructor,Move Semantics,Move Constructor,我是一个初学者,我希望我不会仅仅因为不懂术语而重复发帖,但我已经搜索了Stack Overflow和Google,仍然没有找到我的问题的答案,或者至少是我能理解的答案 我正在为单链表赋值编写一个节点类。该类有两个字段:elem和next。元素是模板化的,下一个是节点指针 我决定编写一个自定义构造函数(以及所有其他构造函数),这样就可以确保每个新节点的next都初始化为nullptr,这样就不会出现错误的指针问题。类标题: template <typename E> class Nod

我是一个初学者,我希望我不会仅仅因为不懂术语而重复发帖,但我已经搜索了Stack Overflow和Google,仍然没有找到我的问题的答案,或者至少是我能理解的答案

我正在为单链表赋值编写一个节点类。该类有两个字段:elem和next。元素是模板化的,下一个是节点指针

我决定编写一个自定义构造函数(以及所有其他构造函数),这样就可以确保每个新节点的next都初始化为nullptr,这样就不会出现错误的指针问题。类标题:

template <typename E>
class Node {
public:

    //Constructors
    Node();
    Node( const Node<E> &other);           //copy
    Node<E>& operator=( Node<E> other );   //copy asn
    Node( Node&& other );                  //move
    Node<E>& operator=( Node<E>&& other ); //move asn
    ~Node();

    // {...Getters and setters and the like...}

private:
    E elem{};       //datatype independent element
    Node<E>* next;  //pointer to next list item
};
模板
类节点{
公众:
//建设者
Node();
节点(常量节点和其他);//复制
节点和运算符=(节点其他);//复制asn
节点(节点和其他);//移动
节点和运算符=(节点和其他);//移动asn
~Node();
//{…接球手和接球手之类的…}
私人:
E elem{};//数据类型独立元素
Node*next;//指向下一个列表项的指针
};
我的问题是如何编写move构造函数。据我所知,move构造函数的基本轮廓如下:

myClass( myClass&& otherMyClassObj ) {

    // Step 1: Steal object's resources

    myClassField = otherMyClassObj.myClassField;
    myClassOtherField = otherMyClassObj.myClassOtherField;
    /* ...etc... */

    // Step 2: Set other object to a valid but default state so it will be deleted

    otherMyClassObj.myClassField = <whatever is default for type>;
    otherMyClassObj.myClassOtherField = <whatever is default for type>;
    /*...etc...*/
}
myClass(myClass&&otherMyClassObj){
//步骤1:窃取对象的资源
myClassField=otherMyClassObj.myClassField;
myClassOtherField=otherMyClassObj.myClassOtherField;
/*……等等*/
//步骤2:将其他对象设置为有效但默认的状态,以便将其删除
otherMyClassObj.myClassField=;
otherMyClassObj.myClassOtherField=;
/*……等等*/
}
然而,当我试图应用这个大纲在我的类中编写move构造函数时,我遇到了一个问题:elem的默认状态是什么,我不知道它的类型,因为它是在运行时确定的?我的移动构造函数代码:

template <typename E>
Node::Node( Node&& other ) {

    next = other.next;
    elem = other.elem;

    other.next = nullptr;
    other.elem = /* ???? */
}
模板
节点::节点(节点和其他){
next=other.next;
elem=其他.elem;
other.next=nullptr;
其他.elem=/**/
}
我能想到的唯一解决方案是手动调用另一个上的析构函数,但这似乎是草率和错误的。我不能使用nullptr,因为elem不一定是指针,但我不能使用0,因为它可能是指针。我考虑过的另一种可能性是以某种方式直接在elem上调用std::move(),但我不确定具体怎么做,而且在move构造函数中调用move构造函数似乎本质上是错误的

在这个问题上,我非常感谢你的帮助。请不要提出非标准的图书馆建议——我很想使用它们,但我的教授对我们使用的图书馆非常严格

只需移动每个成员

template <typename E>
Node::Node<E>( Node<E> && other ) : next(std::move(other.next)), elem(std::move(other.elem))
{
}
模板
Node::Node(Node&&other):next(std::move(other.next)),elem(std::move(other.elem))
{
}
请注意,我不确定上面的确切模板语法


遵守五的规则是件好事,但是如果您不想在某些构造函数、赋值运算符或析构函数中做任何特殊的事情,那么请考虑使它们
=default
。这对您来说更容易、更安全。

关于
E
我们只知道有
默认c-tor
,否则代码将无法编译

总的来说,c-tor的行动将像沃纳·亨兹建议的那样。不过,我建议您也重置指针

template <typename E>
Node::Node<E>( Node<E> && other ) :
               next(std::move(other.next)),   // line 1
               elem(std::move(other.elem)){   // line 2
        // change to NULL for pre C++11
        other.next = nullptr;  // line 3
}
最后说明: 此处不需要
{}

private:
    E elem{};       //datatype independent element
这是足够的:

private:
    E elem;       //datatype independent element

您真的需要设置默认值吗?好的,移动构造函数应该让moved from对象保持未指定但可破坏的状态在大多数情况下,包括您的情况,您应该在移动构造函数中使用
std::move
。@NathanOliver我不知道。如果我在写移动构造器,我是必须手动完成,还是它为我完成?@Bathsheba这很有道理,几乎太简单了如果您编写
template节点(Node&&other)=default
,那么编译器将为您生成move构造函数:它将对每个成员调用
std::move
。这样做的好处是,如果您添加了一个新成员而忘记修改构造函数,那么您的代码将不会爆炸!更好的是,只需要安排一些事情,这样你就可以依靠编译器隐式地生成move构造函数了。哇!真的就这么简单!非常感谢。
private:
    E elem;       //datatype independent element