c++ - 将从一个函数返回的 vector 传递给另一个函数

标签 c++ templates gcc4.7

我有一个返回字符串 vector 的函数

std::vector<std::string> getNames()
{
std::vector<std::string> names;
names.push_back("one");
return names;
}

我有另一个类,其构造函数具有以下签名(这实际上来自 TCLAP):

ValuesConstraint(std::vector<T>& allowed);

如果我尝试执行以下操作,我会收到错误

ValuesConstraint<std::string> A( getNames() );

但当我执行以下操作时则不然

std::vector<std::string> v = getNames();
ValuesConstraint<std::string> A( v );

这会出现在 GCC 4.4.7 中,但不会出现在 VS2010 中。错误如下:

error: no matching function for call to ‘TCLAP::ValuesConstraint<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::ValuesConstraint(std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >)’

note: candidates are: TCLAP::ValuesConstraint<T>::ValuesConstraint(std::vector<T, std::allocator<_CharT> >&) [with T = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]

note:                 TCLAP::ValuesConstraint<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::ValuesConstraint(const TCLAP::ValuesConstraint<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&)

为什么会出现此错误,我该如何将返回值直接传递给构造函数?

最佳答案

Why is this error occurring, and what can I do to pass the return value directly to the constructor?

ValuesConstraint<>的构造函数接受左值(对非 const 的左值引用只能绑定(bind)到左值),而不返回引用类型的函数调用表达式是右值。

左值引用无法绑定(bind)到右值,因此您无法将临时值传递给 ValuesConstraint<> 的构造函数(临时值是右值)。

如果您发现术语左值右值令人困惑,您可以(直观地)将左值视为:

  • 命名变量(实际上是标识符);和/或
  • 可以获取地址的对象(实际上是表达式)

它们通常表示可以在程序中重复引用的具有稳定标识的对象,从该对象隐式移动安全(因为它们可以稍后在程序中引用)。

相反,您可以将右值视为:

  • 未命名的对象,例如临时对象;和/或
  • 文字(如 42false3.14 );和/或
  • 表示具有“不稳定”身份的对象(如 std::move() 的结果)的表达式,这些对象即将被移出

它们通常表示无法在程序中重复引用的对象(或者在通过显式调用 std::move() 重新分配它们之前 promise 不再引用的对象),并且是因此,可以安全地离开。

不过,请对上述内容持保留态度 - 它只是一个指南,您可以使用它来建立一些关于什么是值类别以及如何判断某个表达式的值类别是什么的直觉。从形式上来说,事情有点复杂,而且上述概括并不总是正确的。

所以回到你的例子,在这种情况下:

std::vector<std::string> v = getNames();
//                       ^
//                       Named variable! Can take its address! lvalue!
ValuesConstraint<std::string> A( v );
//                               ^
//                               OK! The constructor accepts an lvalue
//                               reference to non-const, and I am giving
//                               it an lvalue

您将左值传递给构造函数,一切正常。另一方面,在这种情况下:

ValuesConstraint<std::string> A( getNames() );
//                               ^^^^^^^^^^
//                               getNames() returns a vector by value, this
//                               means a temporary will be constructed as the
//                               return value of the function, and temporaries
//                               are unnamed... so, that's an rvalue!
//                               And the constructor accepts an lvalue reference
//                               to non-const! So this is an ERROR!

您正尝试将右值传递给接受非 const 的左值引用的函数。 (换句话说,它需要一个可修改的左值)。这是非法的,编译器会提示它。

This occurs in GCC 4.4.7 but not in VS2010

这是因为 VC10 实现了一个不兼容的编译器扩展,允许将右值绑定(bind)到对非 const 的左值引用。 。但请注意,这不是标准行为,如果您想编写可移植代码,则不应依赖它(实际上,我建议您无论如何都不要依赖它)。

As suggested by Jesse Good in the comments ,将警告级别提高到 4,以便从编译器获得警告并检测您使用此非标准扩展的情况。

关于c++ - 将从一个函数返回的 vector 传递给另一个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17535712/

相关文章:

C++ 隐式模板实例化

c - 函数未被调用

c++ - 使用 -O3 编译时出现奇怪的段错误

c++ - *这会调用构造函数?

C++11:有没有办法强制类只能用作右值?

c++ - Qt4 中的析构函数

c++ - 候选函数和声明顺序

c++ - 检测堆栈损坏

c++ - 返回模板的模板

c++11 - Mac 上的 gcc 4.7.3 和 gdb 7.6 - 奇怪的步进问题