【问题标题】:G++ and CL(VS2017) both compiled successfully but the cl-compiled executable run abnormallyG++和CL(VS2017)都编译成功但是cl编译的可执行文件运行异常
【发布时间】:2019-08-02 12:42:56
【问题描述】:

我编写了一个 LinkedList 类和一个测试函数来测试我的类。但是,我在编译和运行程序时遇到了一些问题。共有三个文件:test.cppLinkedList.cppLinkedList.h

test.cpp:

#include "LinkedList.cpp"
#include <string>
#include <iostream>
using namespace std;

// Loading Array into Linked List for testing
template <class T, size_t n>
void fillArrayIn(LinkedList<T> &list, T (&arr)[n])
{
     unsigned int length = sizeof(arr) / sizeof(*arr);
     for (unsigned int i = 0; i < length; i++)
     {
          list.append(arr[i]);
     }
}

int main()
{

     // Integer LinkedList
     cout << "=====================================" << endl;
     cout << "Test for Integer LinkedList" << endl
          << endl;
     LinkedList<int> intList;

     cout << "Is List Empty? " << (intList.isEmpty() ? "Yes" : "No") << endl
          << endl; // Test isEmpty()

     int intArray[] = {1, 2, 5, 6, 9, 0, 1};
     fillArrayIn(intList, intArray); // Test appending
     cout << "Array Loaded" << endl;
     cout << "Is List Empty? " << (intList.isEmpty() ? "Yes" : "No") << endl;
     intList.printAll();

     intList.insert(*(new int(100)), 3); // Test insertion
     cout << endl
          << "Insert 100 to position 3" << endl;
     intList.printAll();
     cout << "Insert integer outside the List: "
          << (intList.insert(*(new int(100)), 100) ? "Success" : "Fail") << endl
          << endl; // Test illegal insertion

     cout << "Find the position of integre 9: " << intList.positionOf(9) << endl; // Test get the position of element in List
     cout << "Find the position of not existed element: " << intList.positionOf(20) << endl
          << endl; // Test get the position of not existed element

     cout << "The element at position 0 is " << *(intList.get(0)) << endl; // Test get element
     cout << "The element at position 7 is " << *(intList.get(7)) << endl;
     cout << "The element at position 8 is " << intList.get(8) << endl
          << endl;

     cout << "Deleting 100 from list: "
          << (intList.remove(*(new int(100))) ? "Sucess" : "Fail") << endl;
     intList.printAll();
     cout << "Deleting not existed element from list: "
          << (intList.remove(*(new int(20))) ? "Sucess" : "Fail") << endl;
     intList.printAll();
}

LinkedList.cpp:

#include <string>
#include <iostream>
#include "LinkedList.h"
using namespace std;

template <class T>
LinkedList<T>::LinkedList()
{
    head = new Node(NULL);
}

template <class T>
void LinkedList<T>::append(T &_data)
{
    Node *current = head;
    while (current->next)
    {
        current = current->next;
    }
    current->next = new Node(&_data);
    // cout << _data <<" has been appended to the list."<<endl;
}

template <class T>
bool LinkedList<T>::insert(T &_data, const int position)
{
    Node *current = head;
    Node *previous = head;
    for (int i = position + 1; i > 0; i--)
    {
        if (!current->next)
            return false;
        previous = current;
        current = current->next;
    }
    previous->next = new Node(&_data);
    previous->next->next = current;
    return true;
}

template <class T>
T *LinkedList<T>::get(int position)
{
    Node *current = head;
    for (int i = position + 1; i > 0; i--)
    {
        if (!current->next)
            return NULL;
        current = current->next;
    }
    return current->data;
}

template <class T>
bool LinkedList<T>::isEmpty()
{
    if (head->next)
        return false;
    return true;
}

template <class T>
bool LinkedList<T>::remove(const T &_data)
{
    Node *current = head;
    Node *previous = current;
    while (current->next)
    {
        previous = current;
        current = current->next;
        if (*(current->data) == _data)
        {
            previous->next = current->next;
            return true;
        }
    }
    return false;
}

template <class T>
int LinkedList<T>::positionOf(const T &_data)
{
    Node *current = head;
    unsigned int position = -1;
    while (current->next)
    {
        current = current->next;
        position++;
        if (*(current->data) == _data)
            return position;
    }
    return -1;
}

template <class T>
void LinkedList<T>::printAll()
{
    Node *current = head;
    while (current->next)
    {
        current = current->next;
        cout << *(current->data) << "  ";
    }
    cout << endl;
}

template <class T>
class LinkedList<T>::Node
{
  public:
    Node(T *_data) : data(_data) {}
    T *data;
    Node *next;
};

LinkedList.h:

#ifndef LINKEDLIST_H
#define LINKEDLIST_H

template <class T>
class LinkedList
{
  public:
    LinkedList();
    void append(T &);
    bool insert(T &, const int);
    T *get(int);
    bool isEmpty();
    bool remove(const T &);
    int positionOf(const T &);
    void printAll();

  private:
    class Node;
    Node *head;
};

#endif

当我用g++编译我的程序时,它编译成功并给出了预期的结果:

=====================================
Test for Integer LinkedList

Is List Empty? Yes

Array Loaded
Is List Empty? No
1  2  5  6  9  0  1

Insert 100 to position 3
1  2  5  100  6  9  0  1
Insert integer outside the List: Fail

Find the position of integre 9: 5
Find the position of not existed element: -1

The element at position 0 is 1
The element at position 7 is 1
The element at position 8 is 0

Deleting 100 from list: Sucess
1  2  5  6  9  0  1
Deleting not existed element from list: Fail
1  2  5  6  9  0  1

当我尝试用cl(VS2017)编译我的程序时,编译也成功了。但是,当我运行程序时,它会卡在某个点。运行结果:

=====================================
Test for Integer LinkedList

Is List Empty? No

后来,我尝试在 Visual Studio 中创建一个项目。令人惊讶的是,这一次,它运行没有任何问题。 如何正确使用cl 进行编译?如果你能给我一些提示,谢谢!我是 C++ 的新手。

顺便说一句。 cl生成的目标文件和可执行文件超过200KB,远大于g++生成的14KB左右。

【问题讨论】:

标签: c++ visual-studio compilation g++


【解决方案1】:

您的空列表检查使用Node 属性next

/* ... */
if (head->next)
/* ... */

在使用Node的指针参数的构造函数后,next没有显式初始化。

Node(T *_data) : data(_data) {}

这些行都是与输出的一阶差分相关的

列表是空的吗?没有
列表是空的吗?是的

我倾向于对初始化持偏执态度,并会使用修改后的构造函数进行显式初始化:

Node(T *_data) : data(_data), next(NULL) {}

【讨论】:

  • 我们不能依赖——指针被隐式初始化,就像所有其他基本数据类型(int、double等)也不是.我认为这是语言的弱点,但它就是这样......
  • 虽然我完全同意你的看法(现在和我回答的已删除部分),但我不明白你的意思。 @Aconcagua 看来您同意我写的内容...即这就是为什么我偏执并且不依赖它的原因......我删除了,因为它可能是错误的......
  • [@$*#!] – 似乎又错过了标准中的一些更新......如果我读到 cppreference 对,因为 C++11 (甚至C+03?)成员零初始化的。你会读一样的吗?
  • @Aconcagua 在某些情况下,是的。但是,如果我没看错的话,它们都不适用于这里,那至少需要next()。而且我什至不确定是() == “大括号”还是大括号== {}。顺便说一句,我对那些可以自己寻找疏忽的人印象深刻(请把它当作一种恭维),但这不是我的“辩护”。较新的标准或多或少地通过了我的工作领域...... ;-)
  • 那么谢谢你的花...(){} 大部分是等效的,不过似乎有一些极端情况,例如。 G。根据我们一些高度装饰(>100k 声誉)C++ 专家对一些我不记得的问题的评论,这些引用显然被初始化为带有大括号的悬空临时对象(括号不会编译)...
【解决方案2】:

我建议对您的代码进行以下更改。我不知道这是否会改变行为,但值得一试。

  1. List的构造函数中将head初始化为nullptr

    template <class T>
    LinkedList<T>::LinkedList() : head(nullptr) 
    {
        // Creating a Node with NULL does not make sense to me.
        // head = new Node(NULL);
    }
    
  2. Node的构造函数中将next初始化为nullptr。让它未初始化肯定会导致问题。

    Node(T *_data) : data(_data), next(nullptr) {}
    

【讨论】:

    猜你喜欢
    • 2010-11-09
    • 2018-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-30
    • 2011-06-07
    • 1970-01-01
    相关资源
    最近更新 更多