2015-02-06 116 views
0

我有一個在C++中編寫的兩個測試程序的例子。第一個工作正常,第一個錯誤。請幫我解釋一下這裏發生了什麼。爲什麼這些字符串不會在C++中連接?

#include <iostream> 
#include <string> 
#include <stdint.h> 
#include <stdlib.h> 
#include <fstream> 
using namespace std; 

string randomStrGen(int length) { 
static string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; 
string result; 
result.resize(length); 
for (int32_t i = 0; i < length; i++) 
    result[i] = charset[rand() % charset.length()]; 
return result; 
} 

int main() 
{ 
ofstream pConf; 
pConf.open("test.txt"); 
pConf << "rpcuser=user\nrpcpassword=" 
    + randomStrGen(15) 
    + "\nrpcport=14632" 
    + "\nrpcallowip=127.0.0.1" 
    + "\nport=14631" 
    + "\ndaemon=1" 
    + "\nserver=1" 
    + "\naddnode=107.170.59.196"; 
pConf.close(); 
return 0; 
} 

它打開'test.txt'並寫入數據,沒問題。然而,這並不是:

#include <iostream> 
#include <string> 
#include <stdint.h> 
#include <stdlib.h> 
#include <fstream> 
using namespace std; 

string randomStrGen(int length) { 
static string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; 
string result; 
result.resize(length); 
for (int32_t i = 0; i < length; i++) 
    result[i] = charset[rand() % charset.length()]; 
return result; 
} 

int main() 
{ 
ofstream pConf; 
pConf.open("test.txt"); 
pConf << "rpcuser=user\n" 
    + "rpcpassword=" 
    + randomStrGen(15) 
    + "\nrpcport=14632" 
    + "\nrpcallowip=127.0.0.1" 
    + "\nport=14631" 
    + "\ndaemon=1" 
    + "\nserver=1" 
    + "\naddnode=107.170.59.196"; 
pConf.close(); 
return 0; 
} 

第二個程序唯一的區別是'rpcpassword'已被移動到下一行。

[email protected]:~/Desktop$ g++ test.cpp 
test.cpp: In function ‘int main()’: 
test.cpp:23:6: error: invalid operands of types ‘const char [14]’ and ‘const char [13]’ to binary ‘operator+’ 
    + "rpcpassword=" 
+1

不同之處在於'std :: string'具有'operator +'重載用'const char *'連接。 – 2015-02-06 01:14:04

+0

Aasmund的答案是正確的,但偶然相鄰的字符串文字會在編譯器的早期階段被串聯(例如,即使它們位於源中的不同行上,「abc」「def」也會變成「abcdef」)。因此,如果刪除'randomStrGen(15)'之前和之後的所有'+',它不僅能夠正確編譯,而且可以使用更少的內存並且運行得更快。 – 2015-02-06 01:21:05

+0

FWIW - 使用連接的示例[here](http://ideone.com/MEoMgF)... – 2015-02-06 01:31:37

回答

4

"rpcuser=user\nrpcpassword=" + randomStrGen(15) + "\nrpcport=14632"基團如("rpcuser=user\nrpcpassword=" + randomStrGen(15)) + "\nrpcport=14632"。在這裏,+總是與一個類類型的參數一起使用,所以你在重載解析後得到std::string::operator+

"rpcuser=user\n" + "rpcpassword=" + randomStrGen(15)羣像("rpcuser=user\n" + "rpcpassword=") + randomStrGen(15)。在這種情況下,第一個+用於兩個非類別類型,因此它不會超載,並且語言不會爲兩個const char []值定義+。 (我來自舊C,所以我有點不只是將它們添加爲char * s,並且在運行時爲您提供了一個很好的SIGSEGV。)

+0

這兩個答案都非常有幫助,你的分組用圓括號做了點擊。我不喜歡這樣一個事實,即在我不知道它的情況下它是超載的,看起來這會導致程序員不知道到底發生了什麼。我將確保改變我對字符串文字的使用。 – 2015-02-06 01:32:42

+0

我應該使用圓括號來使我的觀點更清晰,所以這也得到了我的贊同:-)(只要你使用C++,你最好習慣於重載......) – 2015-02-06 01:45:08

5

在C++字面("foo")字符串是不是類型string;它的類型爲const char[x],其中x是字符串文字的長度加1.並且字符數組不能與+連接。然而,字符數組可以string連接,並且結果是string,其可以進一步與字符數組連接。因此,"a" + functionThatReturnsString() + "b"工程,但"a" + "b"沒有。 (請注意,+被左結合;它被施加到最左邊的兩個操作數,然後再對結果和所述第三操作數,等等。)

+3

由於連續的兩個字符串被自動連接,所以OP應該刪除「+」。 – 2015-02-06 01:17:07

+0

那麼爲什麼第一個工作? – 2015-02-06 01:17:36

+0

@ user2676680有很多['operator +'的非成員重載](http://en.cppreference.com/w/cpp/string/basic_string/operator%2B),它們採用'const char *'和'的std :: string'。但是,沒有內置的'operator +',它帶有兩個'const char *'。 – 2015-02-06 01:20:01

相關問題