2012-12-19 18 views
0

計劃1:使用lambda函數來模擬詞法錯誤有沒有不可預知的性能/實現問題?

#include <iostream> 

std::string Hello(void){return "Hello";} 
std::string World(void){return "world!";} 

int main(){ 

    std::cout << Hello() << " " << World() << std::endl; 
} 

功能您好()和世界()在全局命名空間存在。
這意味着它們可以通過聲明後的任何其他函數調用(或者在本例中,我提供了定義並且不需要首先聲明)。

我有這個問題,因爲隨着我的項目變得越來越大,我包含了更多的頭文件,這些頭文件用很多函數填充全局名稱空間,並且我冒着函數簽名衝突,或者更糟的是,意外地調用了錯誤的函數只應該被稱爲另一個函數的子任務。

我想遵循功能分解任務到子任務的paradaim,因此它對特定函數在另一個特定函數的範圍之外被調用是沒有意義的。

這是一個解決方法,除了由於縮進深度導致代碼變得不可讀,我想知道是否有任何性能或實現問題。 lambda函數對我來說目前有點神奇,所以我對無法預料的危險感到好奇。

方案2:

#include <iostream> 

int main(){ 

    auto Hello = [](void) -> std::string{return "Hello";}; 
    auto World = [](void) -> std::string{return "world!";}; 

    std::cout << Hello() << " " << World() << std::endl; 
} 

你好()和世界()封裝內main()和不能從外部主()的範圍被調用。
這一切是不同的?

+6

命名空間有什麼問題? – delnan

+2

'使用名稱空間'太簡單了,因爲可以在多個模塊中使用相同的名稱空間。一個很好的例子,簡單地說就是全局的,好的命名空間。 –

回答

0

首先,它被稱爲「命名空間」。其次,這種lambda沒有任何缺點。實際上,它們有好處,因爲現在可以在其中使用局部變量,這允許重新使用更多的邏輯。

0

我不會這樣做。在你的情況下,你最終會創建一個巨大的函數來允許裏面的lambda定義,並且你最終會得到一些函數,這些函數的內容很難維護。

在C++ 11和lambdas之前已經有非常大的項目,並且碰撞的風險已經通過不同的方式進行管理,包括已經提到的DeadMG的命名空間,以及類和麪向對象的設計以及其他形式的封裝(在實現文件的命名空間級別定義本地函數爲static,強制內部鏈接並避免與其他翻譯單元發生衝突,如果您仔細選擇有意義的名稱作爲標識符,則應避免99%的衝突。如果你真的打算在大型項目上工作,考慮閱讀John's Lakos Large Scale C++ Software Design

1

在C++中實現你想要的東西的首選機制是將一些東西(函數,類型,對象)私有化(不是關鍵字的意義上的可訪問性),使得它們不能在另一個模塊中被命名。這可以完全防止碰撞。

例如,考慮由一個頭文件的模塊:

// List dependencies 
#include <string> 

// It's customary to put things in a namespace 
// Note that namespaces are commonly cross-module 

namespace ns { 

// Declarations visible to all 
std::string hello_world(); 

} // ns 

和這樣的實現:

// include header listed above 
#include <header.hpp> 

// This contains declarations visible to this module only 
namespace { 

std::string hello_part(); 

// This is both a declaration and a definition 
std::string world_part() 
{ return "world!"; } 

} // namespace 

// Definition of function declared in header 
std::string ns::hello_world() 
{ 
    // Implemention defers to private parts that are visible here 
    return hello_part() + " " + world_part(); 
} 

// Definition of private function 
// We need to reopen the unnamed namespace for that 

namespace { 

std::string hello_part() 
{ return "Hello"; } 

} // namespace 

現在另一個模塊可以根據自己的,這需要不聲明另一個hello_part是一個具有相同聲明的函數,甚至是一個函數,並且不會有衝突。將有兩個不同的獨立實體 - 很像for聲明可以有自己的int i;變量與干擾沒有任何其他i

至於你的問題的其他部分,上述hello_partworld_part作爲普通的舊函數或作爲函數對象(通過lambda表達式或其他)進行實現並不重要。但請記住,由於它們沒有關閉任何東西,它們不是什麼關閉。 C++ lambda表達式允許關閉任何東西,包括局部變量(也稱爲本地捕獲),但是類型系統的表達能力不足以允許upwards funarg problem在某些情況下不付出小處罰。儘管如此,C++的信條不會發生在你的背後,你需要通過例如C++來闡明這種懲罰。 std::function。對於這些情況,我會反對lambda表達式,因爲我認爲有更好的選擇(我不會在這裏擴展)。

一般來說,決定是否要使用lambda表達式是一個考慮因素,它不會(也不應該)影響程序的模塊性。

更長和更詳細的答案將解釋範圍和可見性,聲明和實現,名稱空間,模塊和可訪問性的不同作用,它們都可用於使程序模塊化。最好不要混淆它們。我的例子使用除了可訪問性之外的所有這些東西來實現它的需求,但它遠非實現它的唯一方法。

+0

好的寫法,但它並沒有真正回答這個問題 - 「*我想知道是否有任何性能或實現問題。」在我看來,答案是'不',即使其他設計更多實際的。 – ildjarn

+0

@ildjarn第二段到最後一段,但我需要修改它。 –

相關問題