2017-06-22 91 views
-6
#include"iostream" 
using namespace std; 

class xxx 
{ 
    public: 
     char **a; 
     xxx(); 
     ~xxx(); 
}; 
xxx :: xxx() 
{ 
    a=new char*; 
    *a="10"; 
    cout<<endl<<*a; // works fine 
    cout<<"Enter name:"; 
    cin>>*a;   // segmentation fault?? 
} 
xxx :: ~xxx() 
{ 
    delete a; 
} 

main() 
{ 
    xxx x; 
    cout<<*x.a; 
} 

爲什麼我不能使用cin更改名稱字段? 當我調用構造函數時,它將值賦給變量,但編輯時顯示以下錯誤: 程序已停止工作。 方法也會出現同樣的問題。我錯過了什麼。在你的代碼爲什麼此代碼顯示分段錯誤?

+0

'main'回報'int'。 –

+0

使用std :: string。 – 2017-06-22 13:22:59

+1

你應該閱讀[很好的C++書](https:// stackoverflow。com/questions/388242/the-definitive-c-book-guide-and-list) – nefas

回答

0

問題可最小化到這個片段的無效代碼:

char *p = "foobar"; // should not compile, but would on many compilers due to backward compatibility 
p[0] = 'F'; 

問題是你要修改內存中的字符串字面所在是UB。

1

xxx的構造函數中,*a被初始化,所以它指向字符串的第一個字符。

然後聲明cin >> *a嘗試修改字符串文字。這給未定義的行爲。您所描述的症狀是未定義行爲的一種可能結果。

一個更簡單的實施例,而不xxx類的混淆細節將是

#include <iostream> 

int main() 
{ 
    char **a = new char *; 
    *a = "10"; 
    std::cout << std::endl << *a; // works fine 
    std::cout << "Enter name:"; 
    std::cin >> *a;   // undefined behaviour here 
} 

雖然,與任何形式的未定義的行爲,特定結果/症狀不被保證。

你可以試試你的編譯器轉向了警告級別,其結果很可能會收到可疑轉換警告在聲明中*a = "10"(例如,轉換的東西constconst)。大多數現代C++編譯器(以及相當一些較舊的編譯器)都被配置爲默認情況下不提醒這些事情,但可以配置爲發出此類警告。打開編譯器警告,並注意它們,有助於減少這種類型的未定義行爲。

1

對於這個問題,代碼的問題很簡單。在你的構造:

xxx :: xxx() 
{ 
    a=new char*; 
    *a="10"; 
    cout<<endl<<*a; // works fine 
    cout<<"Enter name:"; 
    cin>>*a;   // segmentation fault?? 
} 

您試圖讀入一個已經初始化字符串文字,然後引起Undefined Behavior。如果你想要做這樣的事情,並且使用的是C++,你應該切換到std::string,這將使你的代碼簡單了很多無需處理原始字符串字面量和指針,如下:

#include <iostream> 
#include <string> 

class xxx 
{ 
    public: 
     std::string a; 
     xxx(); 
     ~xxx(); 
}; 
xxx :: xxx() 
{ 
    a = "10"; 
    std::cout << std::endl << a; 
    std::cout << "Enter name:"; 
    std::cin >> a; 
} 

int main() 
{ 
    xxx x; 
    std::cout<< x.a; 
} 

在這個例子中,代碼如a=new char*;delete a;與析構函數一起被刪除。我做的其他更改包括將代碼更改爲不使用using namespace std;Read爲什麼它被認爲是不正確的做法),並使用返回類型int代替main()。此外,我還包括<string>庫以及std::string。最後,作爲另一項建議,因爲std::cin將只讀取第一個字傳遞給它而忽略其他,如果你想讀一個全名那麼你可以使用getline()如下:

//std::cin >> a; becomes... 
getline(std::cin, a);