接受右值引用作为参数的方法的 Swig 行为
Swig behavior for methods that accept rvalue reference as a parameter
Swig 文档指定它有意忽略移动构造函数。但是它没有指定它对接受 rvlaue 引用的方法的作用,例如:
class AAA {
public:
AAA() {}; // generates java code
AAA(const AAA& a) {}; // generates java code
AAA(AAA&& a) {}; // ignored by swig, no java code generated
virtual void move(const std::string& str); // generates java code
virtual void move(std::string&& str); // also generates java code, but accepts SWIGTYPE_p_std__string as a parameter instead of String
};
这些方法的行为会有所不同吗?有没有一种在 swig 中使用右值参数的首选方法?还是我不应该使用它们?
通常对于编写良好的 C++ 代码,您会期望两个重载函数或构造函数的相同行为是等效的,但需要注意的是右值引用变体很可能会破坏其输入。
所以为了用另一种语言制作界面,这可能并没有真正 1:1 映射到右值试图表达的概念,那么绝大多数时候正确的答案是简单地忽略这些重载。在某些情况下,在内部,SWIG 生成的包装器可能最终会使用这些重载,或者可以通过您的一些努力来编写,但这只是一种优化。如果您要跨越 JNI 边界,那么这可能不太可能成为您最大的性能瓶颈。 (做任何事情之前都要测量它)。
在某些语言中(例如 Python、Lua?)您可能会想利用这样一个事实,即您的对象是引用计数的,这对您有利,并且(对这些语言来说是透明的)编写一个类型映射如果我们是唯一持有对象引用的人,它会选择使用哪个重载。我认为即使这种情况也是错误的(也是过早的优化),因为:
- 如果语言支持这样的构造,则围绕弱引用存在竞争条件。很难发现和避免这种情况。
即使您只有一个对您的(例如)Python 对象的引用,但仍然可以对同一个 C++ 对象进行多个引用,例如:
struct a {};
a& blah() {
static a a;
return a;
}
有
import test
a=test.blah()
b=test.blah()
c=test.blah()
a、b 和 c 都只有 1 个引用,但移动它们显然是错误的。而且几乎不可能证明什么时候是安全的。
所以我的意思是:除非你别无选择,否则请忽略它们。有时您可能会遇到这样的情况,其中唯一的选择是调用一个接受右值引用的函数。您可以包装这些函数,但需要根据具体情况来完成,因为您需要了解被包装的 function/constructor 的语义。
Swig 文档指定它有意忽略移动构造函数。但是它没有指定它对接受 rvlaue 引用的方法的作用,例如:
class AAA {
public:
AAA() {}; // generates java code
AAA(const AAA& a) {}; // generates java code
AAA(AAA&& a) {}; // ignored by swig, no java code generated
virtual void move(const std::string& str); // generates java code
virtual void move(std::string&& str); // also generates java code, but accepts SWIGTYPE_p_std__string as a parameter instead of String
};
这些方法的行为会有所不同吗?有没有一种在 swig 中使用右值参数的首选方法?还是我不应该使用它们?
通常对于编写良好的 C++ 代码,您会期望两个重载函数或构造函数的相同行为是等效的,但需要注意的是右值引用变体很可能会破坏其输入。
所以为了用另一种语言制作界面,这可能并没有真正 1:1 映射到右值试图表达的概念,那么绝大多数时候正确的答案是简单地忽略这些重载。在某些情况下,在内部,SWIG 生成的包装器可能最终会使用这些重载,或者可以通过您的一些努力来编写,但这只是一种优化。如果您要跨越 JNI 边界,那么这可能不太可能成为您最大的性能瓶颈。 (做任何事情之前都要测量它)。
在某些语言中(例如 Python、Lua?)您可能会想利用这样一个事实,即您的对象是引用计数的,这对您有利,并且(对这些语言来说是透明的)编写一个类型映射如果我们是唯一持有对象引用的人,它会选择使用哪个重载。我认为即使这种情况也是错误的(也是过早的优化),因为:
- 如果语言支持这样的构造,则围绕弱引用存在竞争条件。很难发现和避免这种情况。
即使您只有一个对您的(例如)Python 对象的引用,但仍然可以对同一个 C++ 对象进行多个引用,例如:
struct a {}; a& blah() { static a a; return a; }
有
import test a=test.blah() b=test.blah() c=test.blah()
a、b 和 c 都只有 1 个引用,但移动它们显然是错误的。而且几乎不可能证明什么时候是安全的。
所以我的意思是:除非你别无选择,否则请忽略它们。有时您可能会遇到这样的情况,其中唯一的选择是调用一个接受右值引用的函数。您可以包装这些函数,但需要根据具体情况来完成,因为您需要了解被包装的 function/constructor 的语义。