2017-09-16 90 views
-1

我是學習C++。我發現你通常使用整數來存儲一個值,如果我們想表示沒有值,那麼我們使用-1。例如,從不包含字符串的向量中搜索字符串索引的返回值將是-1。在Javascript中很容易:你只是聲明它是假的。 我經常遇到兩個問題:爲什麼沒有可以是int或false的數據類型?

  • 如果我打算只使用正面的價值觀,我在浪費全部被分配給INT的可用範圍。從-2到-32768的所有數字
  • 如果我打算使用負值,則此方法無用。

我知道,JavaScript是一種完全不同的世界,但是,例如,這樣的數據類型的範圍可以從-1到用C++ 65534。那麼爲什麼C++沒有可以是數字的數據類型呢?還是有一個我忽略的常見編程技術?

+0

你不*使用'-1'。你可以選擇'-32768'或其他一些魔術數字。此外,您可以拋出異常或返回可選對象。 – juanchopanza

+0

你不是真的在浪費它們,除非你可以使用*小*無符號數據類型。在這種情況下,如果找不到該值,可以引發異常。這在概念上更簡潔(將錯誤條件與預期返回值分開),但我不記得這是否是C++中流行的習慣用法。 – chepner

+1

不,'如果我們想表示沒有價值,那麼我們使用-1'並不準確。請注意,string.indexOf在Javascript中也返回-1,因此您可能想要考慮這是爲什麼。 -1表示「沒有價值」的結論是不正確的。 – pvg

回答

3

C++ 17有一個可選的類型,這就是所謂的std ::可選的。

但我想你錯過了一件事。 C++一方面是一種非常現代的編程語言,提供了許多其他現代語言提供的想法。另一方面,它的設計和效率始終保持高效,內存佔用的效率和速度方面的效率。

例如,從在 矢量搜索字符串的指數收益不包含字符串將是-1。在Javascript中是 容易:你只是聲明它是假的。我經常遇到兩個問題: 如果我只打算使用正值,我正在浪費爲整數分配的所有可用範圍 。說了這麼多的人數從-2到-32768

  • 在std :: vector的發現回報結束(),而不是-1時,未找到索引。
  • std :: basic_string :: find不返回int值,但是size_t,這是事實上無符號的問題。是的,-1是使用的字面值,但對於無符號類型-1是最大可表示值。除了剛好一個數值,即最大值,你不會失去任何東西。 -1 one是表示size_t最大值的便捷方式。

在許多實現的size_t的最大值爲18446744073709551615和大多數C++開發者更喜歡不能夠搜索字符串長度超過18446744073709551614更長(這是遠遠beond現實反正)與有效的可選類型的問題擺弄或花費額外的字節的標誌。

即使size_t最大值爲65535,65534的大小不足但65535的大小的概率非常接近零。

0

首先,在C++函數的返回類型在編譯過程中定義這就是爲什麼你不能做這樣的事情

// ... 
if (found) 
    return index; 
else 
    return false; 

有幾種方法來解決這個問題。您必須根據您的應用程序進行選擇。第一個需要考慮的是與STL庫一致。容器爲其元素提供迭代器,並且find將迭代器返回到所請求的元素。如果找不到,它會將一個迭代器返回到容器的過去結束元素。例如,可以寫

// on some container that offers the standard interface 
auto it = container.find(value); 
if (it == container.end()) { 
    // not found 
} 

以上是最乾淨的解決方案。這是如何在STL中的std::vector和其他每個容器發出未找到的值。編寫這樣的代碼的主要優點是可以用其他代碼替換容器,代碼仍然可以工作。或者,如果您使用兼容接口設計自己的容器,則可以將其無縫插入現有代碼。

但是,在其他情況下,這可能無法正常工作。例如,您可能只需要實際的索引,並且可能很難從非連續容器上的迭代器獲取。在這種情況下,您可以使用std::optional。它可以包含一個對象或是空的,並提供一個bool轉換以便於檢查。

std::optional<int> my_find(T value) { 
// ... 
    if (found) // pseudo-condition, depends on the rest of the code 
     return std::optional<int>(index); // explicit, could be more compact 
    else 
     return std::optional<int>();  // default optional is empty 
} 

// elsewhere 
auto i = my_find(); 
if (!i) { 
    // not found 
} 

請注意,上述內容將增加空間開銷以追蹤對象是否存在。如果由於任何原因而無法接受,則可以採用標記值的思想並創建一個緊湊的可選對象,其中標記值在內部用於指示不存在值,並且提供一個接口來檢查該值,並且可能是如果用戶在對象爲空時請求該值,則拋出。類似於

template <typename T, T sentinel_value> 
class CompactOptional { 
private: 
    T value; 

public: 
    CompactOptional(value = sentinel_value): value(value) {} 

    operator bool() { return value != sentinel_value; } 

    // getter and setter according to your needs 
} 

您必須決定當您嘗試獲取不存在的值時會發生什麼,然後就是這樣。前哨值是你不能使用的任何東西,如果使用unsigned,可能是整數類型的最大值。

相關問題