【问题标题】:c++11 - initialize std::string from char* directly with {} constructorc++11 - 使用 {} 构造函数直接从 char* 初始化 std::string
【发布时间】:2017-03-06 16:12:43
【问题描述】:

我有一个接受std::string&的函数:

void f(std::string& s) { ... }

我有一个const char*,它应该是该函数的输入参数。这有效:

const char* s1 = "test";
std::string s2{s};
f(s2);

这不是:

const char* s1 = "test";
f({s1});

为什么这不可能?有趣的是,CLion IDE 没有抱怨,但编译器却是:

no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘std::basic_string<char>&’

【问题讨论】:

  • 你为什么希望它工作?
  • 该函数需要一个引用字符串,而您的第二个选项不这样做。不过,在您的第一个示例中,鉴于您的示例,完全不需要 s1std::string s2 = "test";
  • 有趣的是 CLion IDE 没有抱怨,但编译器却是: -- CLIon 不是编译器。编译器获胜。
  • 如果你想一想const char* 不是std::string 所以它甚至需要创建一个新的临时字符串来传递给函数。但是函数修改你传入的字符串!!所以它不会接受临时的。非常量引用不会绑定到临时对象。
  • 如果你需要一个非常量引用,无论如何你不能传递一个临时的。

标签: c++ string c++11 curly-braces


【解决方案1】:

这与从char const* 构造std::string 无关。

f 需要一个字符串的左值,并且通过在现场创建一个临时实例,您提供了一个右值,它不能绑定到非 const 左值引用。 f(string{}) 同样无效。

【讨论】:

  • 好吧,f 需要 一个左值。使用左值引用参数是您在 C++ 中表达的方式,但这并不意味着“f 需要引用”。
  • @KerrekSB 我不确定我是否理解。我认为该函数需要一个左值引用,如果您传递一个左值,则该引用将绑定到它。
  • 你不能真的“期待参考”。函数用参数调用,参数是表达式,表达式永远不是引用。重要的是表达式是一个左值。引用是一种谈论左值的方式。
  • @KerrekSB 好的,我改变了措辞,现在更好了吗?我将不得不对此进行自我教育。
  • 嗯,不是真的。价值观不“参考”任何东西。一个简单的事实是“f 需要一个左值 std::string”,或者可能是“一个字符串左值”。我不知道有什么更好或更简单的说法。左值只是一种特殊的值。
【解决方案2】:

一种选择是更改您的函数以按值获取字符串,而不是通过引用。然后它将起作用。无论如何,在 C++11 中,有时最好按值传递,而不是按引用传递。

【讨论】:

    【解决方案3】:

    您的函数接收到一个非 const 引用,并且您正在传递一个临时对象,该对象需要一个副本或一个 const 引用参数。两种解决方案,创建另一个函数来接收对象作为右值引用并在其中调用另一个重载

    void f(string&& s) {  f(s); } 
    

    允许临时对象作为参数,或更改函数定义以接收任何对象,但作为常量引用

    void f(const std::string& s) { ... }
    

    【讨论】:

      猜你喜欢
      • 2015-08-05
      • 2017-04-11
      • 2020-05-05
      • 2014-07-25
      • 2015-04-26
      • 2020-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多