Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.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++_Chaining - Fatal编程技术网

C++ 链接方法给了我意外的结果,参数的求值顺序与此相反

C++ 链接方法给了我意外的结果,参数的求值顺序与此相反,c++,chaining,C++,Chaining,Cliffnotes: 在一个案例中,我得到了方法链接,正如我预期的那样,但在另一个案例中,发生了一些有趣的事情 我希望这两个示例具有完全相同的输出: 我已经使用JavaScript做了很多链接,所以当我得知你可以用C++中类似的方法来链接类方法时,我想试试。不过我遇到了一些问题。我不确定是锁链造成了问题还是其他原因 我通过返回对this的引用来进行链接。例如: Class LLL { public: LLL & addNode( ... ); 然后,“添加节点”方法以以

Cliffnotes:

在一个案例中,我得到了方法链接,正如我预期的那样,但在另一个案例中,发生了一些有趣的事情

我希望这两个示例具有完全相同的输出:


我已经使用JavaScript做了很多链接,所以当我得知你可以用C++中类似的方法来链接类方法时,我想试试。不过我遇到了一些问题。我不确定是锁链造成了问题还是其他原因

我通过返回对
this
的引用来进行链接。例如:

Class LLL
{
public:
    LLL & addNode( ... );
然后,“添加节点”方法以以下内容结束:

    ...
    return *this;
}
有2个相关类和3个相关方法

我有一个线性链表类,
LLL
和一个节点类,
Node
。为了尽可能简单,节点只需持有一个
int
(称为
guid
)和一个
next
prev
指针。线性链表将一组节点放入LLL中。这一切都很好,但当我使用链接添加节点时,有时会得到奇怪的结果


下面是一个示例,其中的工作方式与我期望的一样: 现在,我只想尝试一个节点对象:


我不明白发生了什么的一个例子: 看起来上面的两个例子应该有相同的结果

我想我一定是误解了第二个例子中的单节点对象发生了什么

您可以查看上面任一代码板中的代码,我将包含下面第二个示例的完整代码。我将代码设置为一个大文件,这样我就可以把它放在代码板上,但我将在
node.h
node.cpp
lll.h
lll.cpp
main.cpp
中进行注释:

#include <cstdlib>
#include <iostream>
#include <cstring>
#include <ctime>
using namespace std;

// NODE.H ======================================================================*/
// This class holds the data
class Node
{
public:
    Node();
    Node(int guidIn);
    Node(const Node & nodeIn);
    Node & change(int guidIn);
    void commonConstructor();
    // Get the next node
    Node * next();
    // Set the next node
    void   next(Node * nodeIn);
    // Get the previous node
    Node * prev();
    // Set the previous node
    void   prev(Node * nodeIn);
    Node & show();
private:
    int guid;
    Node * nextNode;
    Node * prevNode;
};
/* EOF
   =============================================================================*/

// LLL.H =======================================================================*/
// This is a LLL to hold nodes
class LLL
{
public:
    LLL();
    ~LLL();
    LLL & addNode(const Node & nodeIn);
    LLL & show();
private:
    Node * head;
};
/* EOF
   =============================================================================*/

// NODE.CPP ====================================================================*/
Node::Node()
{
    guid = 0;
    commonConstructor();
}
Node::Node(int guidIn)
{
    guid = guidIn;
    commonConstructor();
}
Node::Node(const Node & nodeIn)
{
    guid = nodeIn.guid;
    commonConstructor();
}
Node & Node::change(int guidIn)
{
    guid = guidIn;
    cout << "-" << guidIn << "-";
    return *this;
}
void Node::commonConstructor()
{
    nextNode = NULL;
    prevNode = NULL;
}
Node * Node::next()
{
    return nextNode;
}
void Node::next(Node * nodeIn)
{
    nextNode = nodeIn;
}
Node * Node::prev()
{
    return prevNode;
}
void Node::prev(Node * nodeIn)
{
    prevNode = nodeIn;
}
Node & Node::show()
{
    cout << guid;
    return *this;
}
/* EOF
   =============================================================================*/

// LLL.CPP =====================================================================*/    
LLL::LLL()
{
    head = NULL;
}
LLL::~LLL()
{
    Node * temp = head;
    while(head)
    {
        temp = head;
        head = head->next();
        delete temp;
    }
}
LLL & LLL::addNode(const Node & nodeIn)
{
    Node * tempNode = new Node(nodeIn);
    if(!head)
    {
        head = tempNode;
    } else
    {
        Node * temp = head;
        while(temp->next())
        {
            temp = temp->next();
        }
        temp->next(tempNode);
    }
    return *this;
}
LLL & LLL::show()
{
    Node * temp = head;
    while(temp)
    {
        temp->show();
        temp = temp->next();
    }
    return *this;
}
/* EOF
   =============================================================================*/

// MAIN.CPP ====================================================================*/    
int main()
{
    Node node;
    LLL lll;
    lll.addNode(node.change(1)).addNode(node.change(2))
        .addNode(node.change(3)).show();

    cout << "\n";
    return 0;
}
/* EOF
   =============================================================================*/
#包括
#包括
#包括
#包括
使用名称空间std;
//NODE.H======================================================================*/
//这个类保存数据
类节点
{
公众:
Node();
节点(int-guidIn);
节点(const节点和nodeIn);
节点和变更(int-guidIn);
void commonConstructor();
//获取下一个节点
节点*next();
//设置下一个节点
下一步作废(节点*nodeIn);
//获取上一个节点
节点*prev();
//设置上一个节点
无效上一个(节点*nodeIn);
Node&show();
私人:
int-guid;
节点*nextNode;
节点*prevNode;
};
/*EOF
=============================================================================*/
//法学硕士=======================================================================*/
//这是用于保存节点的LLL
LLL类
{
公众:
LLL();
~LLL();
LLL和addNode(const Node和nodeIn);
LLL&show();
私人:
节点*头;
};
/*EOF
=============================================================================*/
//NODE.CPP====================================================================*/
Node::Node()
{
guid=0;
公共构造函数();
}
Node::Node(int-guidIn)
{
guid=guidIn;
公共构造函数();
}
Node::Node(const Node和nodeIn)
{
guid=nodeIn.guid;
公共构造函数();
}
节点和节点::更改(int-guidIn)
{
guid=guidIn;
cout next(tempNode);
}
归还*这个;
}
LLL&LLL::show()
{
节点*温度=头部;
while(临时)
{
临时->显示();
temp=temp->next();
}
归还*这个;
}
/*EOF
=============================================================================*/
//MAIN.CPP=========================================================================================================================*/
int main()
{
节点;
LLL-LLL;
lll.addNode(node.change(1)).addNode(node.change(2))
.addNode(node.change(3)).show();

coutC++不能保证子表达式的计算顺序

在你得到这个的例子中:-3--2--1-111 可能发生的情况是:

lll.addNode(   // fourth
node.change(1) // third
)
.addNode(      // fifth
node.change(2) // second
)
.addNode(      // sixth
node.change(3) // this is first
)
.show();       // last

由于给节点的最后一个值是1,并且您在对addnode的所有三次调用中都传递了对该节点的引用,因此lll的所有节点都会得到相同的值。

在第二个版本中,您在同一个节点上调用了许多操作,而不考虑求值顺序的影响。
a.f(b)
A::f(A,b)
类似,其中
A
属于
A
类,编译器可以按照其认为合适的任何顺序自由计算参数
A
b

在您的例子中,当编译器看到表达式
a.foo(b.bar(1)).foo(b.bar(2))
时,它可以在计算
b.bar(2)
后自由地计算
a.foo(b.bar(1))
,然后调用
foo
,这显然会产生与您期望的不同的行为


简而言之,永远不要在同一表达式中多次变异和使用对象。我的理念是,如果可能的话,永远不要变异对象。

从技术上讲,这是未定义的行为,因为您正在更改一个变量(节点)在序列点之间多次。我还猜测,如果您将节点按值(而不是按常量引用)放入列表中,您可能会从列表中获得所需的输出,但它仍然是未定义的行为。

Wow。我知道
a
b
的求值顺序在
a::f(a,b)中
依赖于实现,但我没有意识到链接的含义。
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <ctime>
using namespace std;

// NODE.H ======================================================================*/
// This class holds the data
class Node
{
public:
    Node();
    Node(int guidIn);
    Node(const Node & nodeIn);
    Node & change(int guidIn);
    void commonConstructor();
    // Get the next node
    Node * next();
    // Set the next node
    void   next(Node * nodeIn);
    // Get the previous node
    Node * prev();
    // Set the previous node
    void   prev(Node * nodeIn);
    Node & show();
private:
    int guid;
    Node * nextNode;
    Node * prevNode;
};
/* EOF
   =============================================================================*/

// LLL.H =======================================================================*/
// This is a LLL to hold nodes
class LLL
{
public:
    LLL();
    ~LLL();
    LLL & addNode(const Node & nodeIn);
    LLL & show();
private:
    Node * head;
};
/* EOF
   =============================================================================*/

// NODE.CPP ====================================================================*/
Node::Node()
{
    guid = 0;
    commonConstructor();
}
Node::Node(int guidIn)
{
    guid = guidIn;
    commonConstructor();
}
Node::Node(const Node & nodeIn)
{
    guid = nodeIn.guid;
    commonConstructor();
}
Node & Node::change(int guidIn)
{
    guid = guidIn;
    cout << "-" << guidIn << "-";
    return *this;
}
void Node::commonConstructor()
{
    nextNode = NULL;
    prevNode = NULL;
}
Node * Node::next()
{
    return nextNode;
}
void Node::next(Node * nodeIn)
{
    nextNode = nodeIn;
}
Node * Node::prev()
{
    return prevNode;
}
void Node::prev(Node * nodeIn)
{
    prevNode = nodeIn;
}
Node & Node::show()
{
    cout << guid;
    return *this;
}
/* EOF
   =============================================================================*/

// LLL.CPP =====================================================================*/    
LLL::LLL()
{
    head = NULL;
}
LLL::~LLL()
{
    Node * temp = head;
    while(head)
    {
        temp = head;
        head = head->next();
        delete temp;
    }
}
LLL & LLL::addNode(const Node & nodeIn)
{
    Node * tempNode = new Node(nodeIn);
    if(!head)
    {
        head = tempNode;
    } else
    {
        Node * temp = head;
        while(temp->next())
        {
            temp = temp->next();
        }
        temp->next(tempNode);
    }
    return *this;
}
LLL & LLL::show()
{
    Node * temp = head;
    while(temp)
    {
        temp->show();
        temp = temp->next();
    }
    return *this;
}
/* EOF
   =============================================================================*/

// MAIN.CPP ====================================================================*/    
int main()
{
    Node node;
    LLL lll;
    lll.addNode(node.change(1)).addNode(node.change(2))
        .addNode(node.change(3)).show();

    cout << "\n";
    return 0;
}
/* EOF
   =============================================================================*/
lll.addNode(   // fourth
node.change(1) // third
)
.addNode(      // fifth
node.change(2) // second
)
.addNode(      // sixth
node.change(3) // this is first
)
.show();       // last