2016-09-18 73 views
5

我有以下代码:转换的char *字符串和

#include <iostream> 
using namespace std; 

int main(int argc, char *argv[]) 
{ 
    string &s1 = argv[0];   // error 
    const string &s2 = argv[0];  // ok 

    argv[0] = "abc"; 
    cout << argv[0] << endl;  // prints "abc" 
    cout << s2 << endl;    // prints program name 
} 

我收到s1以下错误:

invalid initialization of reference of type 'std::string& {aka std::basic_string<char>&}' from expression of type 'char*' 

那么为什么编译器接受s2

有趣的是,当我为argv[0]指定一个新值时,s2不会改变。编译器是否忽略它是一个引用并且复制该值?为什么会发生?

我在Code :: Blocks 16.01(mingw)中写这个。有/无-std=c++11

+1

你会说'argv [0]'是一个'std :: string'吗? – Biffen

+0

“那为什么编译器接受s2?”由于隐式转换。 http://stackoverflow.com/questions/4553896/conversion-of-char-to-string –

回答

6

那为什么编译器接受s2呢?

由于恒定的参考可以绑定到一个暂时的,std::string有一个构造可以采取char *为参数。

该赋值构造了一个所谓的“临时”对象,并绑定了一个常量引用。

有趣的是,当我给argv [0]分配一个新值时,s2不会 更改。

它为什么要改变? s2是一个单独的对象。 A std::string对象不保留指向创建它的char *的指针。有很多方法可以创建std::string。实际的字符串由对象拥有。如果std::string由文字字符串构造而成,则将其复制到std::string中。因此,如果文字字符串来自缓冲区,并且随后修改了缓冲区,则它对std::string不起作用。

+0

一个'std :: string'的构造函数接受一个'const char *'作为参数。我错了吗? – skypjack

+0

不,你不是,@ skypjack。这就是为什么我写了“可以采取”,而不是“采取”。 –

5

这条线:

const string &s2 = argv[0]; 

创建新string例如,复制的argv[0]的内容,并结合参考它。之后,输出该副本,现在与argv[0]的实际值无关。

在带引号的行中创建的临时字符串对象生存期被扩展到该块的范围,因为形成了一个const引用。更多信息请参见:Does a const reference prolong the life of a temporary?

+0

谢谢你的链接! –

1

在这两种情况下,代码都会要求编译器构造一个临时对象,其内容为argv[0]的副本std::string。虽然看起来很有趣,也许有用,但是从实际编写代码的角度来看,弄清临时对象并不是必要的,并且会导致混淆。只是创建一个对象:

std::string s1 = argv[0]; 
1

线

const string &s2 = argv[0]; 

等于:

const string &s2 = std::string(argv[0]); 

所以S2包含const引用到一个临时字符串,复制从的argv [内容0]。