为什么使用指针调用 Json::Value::append 会编译?

Har*_*tts 1 c++ jsoncpp

昨天,我在团队的代码中使用 jsoncpp 库遇到了这样的函数:

#include <json/value.h>

Json::Value makeList() {
  Json::Value list(Json::arrayValue);
  list.append(new Json::Value(true));
  return list;
}
Run Code Online (Sandbox Code Playgroud)

它引起了我的注意,因为new在调用中使用list.append泄漏了一些内存,这可以通过简单地删除来修复new。然而,在调试过程中,我意识到Json::Value::append需要aconst Json::Value&aJson::Value&&C++ 不会将指针隐式转换为引用,因此 aJson::Value*不应隐式转换为其中任何一个。

为了证实这一点,我写了自己的简短示例:

#include <iostream>

class Foo {
public:
    int x = 4;
};

void printValue(const Foo& f) { std::cout << "The value is " << f.x << ".\n"; }
void printValue(Foo&& f)      { std::cout << "The value is " << f.x << ".\n"; }

int main() {
    printValue(new Foo());
}
Run Code Online (Sandbox Code Playgroud)

事实上,这会导致编译错误:

own-example.cpp:12:5: error: no matching function for call to 'printValue'
    printValue(new Foo());
    ^~~~~~~~~~
own-example.cpp:8:6: note: candidate function not viable: no known conversion from 'Foo *' to 'const Foo' for 1st argument; dereference the argument with *
void printValue(const Foo& f) { std::cout << "The value is " << f.x << ".\n"; }
     ^
own-example.cpp:9:6: note: candidate function not viable: no known conversion from 'Foo *' to 'Foo' for 1st argument; dereference the argument with *
void printValue(Foo&& f)      { std::cout << "The value is " << f.x << ".\n"; }
     ^
Run Code Online (Sandbox Code Playgroud)

那么,为什么我发现的代码调用了Json::Value::append编译,而玩具示例却没有?

Kon*_*lph 5

Json::Value(new Json::Value())编译是因为

  • @HarryCutts 完全正确。这就是为什么采用单个参数的非复制/移动构造函数“通常”应该标记为“显式”以避免不需要的隐式转换。如果“Json::Value(bool)”构造函数被标记为“explicit”,则“Json::Value(new Json::Value())”将无法编译。([演示](https://ideone.com/VR20Xo)) (2认同)