在 Qt4 中使用 C 11

2021-06-10 09:19:31 字數 3301 閱讀 7719

原文出處:

我們前面介紹了許多 c++ 11 的優點,而且介紹了如何在 qt 5 中使用 c++ 11。但是,qt 5 畢竟只是乙個尚未發布的版本,現在,我們要介紹的是,如何在 qt 4 中使用 c++ 11。

現在,我們可以在 qt 4.7 和 4.8 兩個版本中使用 c++ 11。4.8 則增加了更多關於 c++ 11 的支援。

如果編譯器支援新的特性,qt 提供了許多新的巨集:

q_compiler_rvalue_refs

q_compiler_decltype

q_compiler_variadic_templates

q_compiler_auto_type

q_compiler_extern_templates

q_compiler_default_delete_members

q_compiler_class_enum

q_compiler_initializer_lists

q_compiler_lambda

q_compiler_unicode_strings

qt 4.8 為 qvector、qlist 和 qstringlist 增加了新的建構函式,允許我們使用 c++ 11 提供的初始化器進行初始化。例如:

qvector

<

int> data

;qstringlist ops =

;

qt 提供了許多隱式共享類。這意味著,如果你沒有修改它們,那麼複製操作將會是很高效的(寫時複製)。這些操作對於 std::vector 是無效的,複製 std::vector 會複製所有資料。如果,如果你的**類似這樣:

std::

vector

<

int> m_foo;

// ...

m_foo = getvector(

);

getvector() 函式可能需要構造乙個新的 std::vector,將其複製給乙個臨時變數,然後 std::vector::operator= 運算子則需要銷毀舊的 m_foo,再將這個臨時變數中的全部資料複製到 m_foo。當這條語句結束時,這個臨時的 vector 將會被銷毀,它的析構函式會刪除其所有資料。如果 operator= 簡單地將 m_foo 的資料切換到這個臨時變數的資料,無疑會使這個操作更高效。這樣的話,m_foo 的舊資料要在這個臨時變數銷毀時才去 delete,這就減少了不必要的複製。這就是 c++ 11 的移動語義,它是由右值引用實現的。

即使複製隱式共享的類代價並不昂貴,但也並不意味著沒有**,我們依然要增加和減少引用計數,呼叫 operator= 也不能是 inline 的(因為它得訪問 private 資料,為了二進位制相容,我們不能將其寫作 inline)。下面,來看看 qt 4.8 的 qimage 移動運算子:

#ifdef q_compiler_rvalue_refs

inline

qimage

&operator=

(qimage

&&other)

#endif

我們僅僅是交換了兩個影象的內部資料,比起通常的操作,這樣的操作已經很廉價了。在 qt 中,大部分隱式共享類都是這麼做的。既然所有容器都有大量的這種操作,那麼將 operator= 按照移動語義定義,肯定會提公升 qt 的效能。這也是使用 c++ 11 編譯 qt 的理由之一。

qt 提供了乙個非常方便的 foreach 巨集。你也可以在其它 c++ 庫,比如 boost 中找到類似的東西。qt 的 foreach 僅僅是乙個比較複雜的巨集,c++ 11 則做得更多,將其作為語言的一部分。因此,像下面的**:

foreach

(const

qstring

&option, optionlist)

我們就可以寫成

for

(const

qstring

&option : optionlist)

這二者還是有一點區別的:qt 在遍歷之前將容器進行了複製。對於 qt 容器,這是廉價操作,因為 qt 容器都是隱式共享的,但對於標準庫的容器,這樣做會引發對整個內容的深拷貝。c++ 11 的 foreach 迴圈不需要複製。這意味著,如果你在遍歷過程中新增或者刪除了容器的元素,所帶來的後果是無定義的。

如果容器是共享的,並且不是 const 的,那麼,如果你要支援 c++ 11 的新的 for,應該自己去呼叫容器的begin()end()函式,將容器複製一遍。因此,正確的**應該是這樣的:

template

<

class t>

const t &const_(

const t &t)

for(

auto it : const_(vector)

)

又到了我最喜歡的部分了 ;-p

比起 qt 5 來,lambda 表示式在 qt 4 中應用不是很多,僅僅是在 qtconcurrent 的某些函式中。

我們現在可以在qtconcurrent::run()qtconcurrent::map()中使用 lambda 表示式:

qlist

<

qimage

> images = ...

qfuture

<

void

> future = qtconcurrent::

map(images,

(qimage

&image)

);

如果你正在使用 msvc 2010,那就沒什麼好做的了。你完全可以開始使用 c++ 11 的新特性,比如 lambda 表示式和右值引用。

如果你使用的是 gcc,你需要增加 -std=c++0x 編譯引數,然後在 .pro 檔案中新增:

qmake_cxxflags += -std=c++0x
如果你需要使用 c++ 11 編譯 qt,那麼就使用:

cxxflags="-std=c++0x"

./configure

qt 將會以 c++ 11 編譯,同時相容舊的 c++ **。另外需要說明的是,如果你僅僅使用 c++ 11 編譯自己的程式,是不需要使用 c++ 11 重新編譯 qt 的。

在QT4中使用QTableView製作屬性編輯器

最近在用qt寫的乙個程式中,需要乙個對大量引數進行設定的功能。過去用delphi的經驗是,盡量不要使用qlistview和tgrid來實現,因為涉及到控制項的對齊,介面的重繪等,反而使簡單問題變得複雜。因此這次用qt寫程式時也想當然,用控制項陣列的方式來解決。很快程式寫好了,介面如下 顯示出的效果還...

C 11中使用using的方法

在 c 中 using 用於宣告命名空間,使用命名空間也可以防止命名衝突。在程式中宣告了命名空間之後,就可以直接使用命名空間中的定義的類了。在 c 11 中賦予了 using 新的功能,讓 c 變得更年輕,更靈活。在 c 中可以通過 typedef 重定義乙個型別,語法格式如下 typedef 舊的...

將矩陣鍵盤加入到QT4中使用

這個資料貌似不多,如果找的到貌似也不全,當然也可以將矩陣鍵盤做成外掛程式到qt中,我實施了一下,還是因為資料不全,自己資質也有限,沒能繼續做下去,能使我做下去的也只有這種要耗費大量精力的簡單重複勞動。下面開始講一下我如何將矩陣鍵盤加入到qt4中使用的。首先就是改qt的原始檔,我改了 src gui ...