这些超载有必要吗?

发布于 2024-11-27 07:38:11 字数 902 浏览 0 评论 0原文

我必须编写一个库,其中包含一个采用两个字符串参数的函数:

void foo(const std::string& arg1, const std::string& arg2);

我的库将由一些不喜欢 C++ 并且只使用 const char* 的人使用。

为了满足他们的喜好,我更改了原型:

void foo(const char* arg1, const char* arg2);

并使我的第一个版本成为一个简单的内联调用:

inline void foo(const std::string& arg1, const std::string& arg2)
{
  foo(arg1.c_str(), arg2.c_str());
}

当然,感谢 std::string 构造函数,只需使用第一个版本。编写此重载只是避免在有人仅传递 const char* 的情况下实例化无用的 std::string

但现在我想知道:这种重载真的有必要还是只是过早的优化?

另外,我觉得这在某种程度上不完整:我是否还应该写 void foo(const char* arg1, const std::string& arg2)void foo(const std:: string& arg1, const char* arg2) 重载?如果我有 3 个、4 个或更多 (n) 个参数怎么办?我应该写 2n 重载吗?

简而言之,您是否遇到过类似的情况?你做了什么选择,为什么?

谢谢。

I have to write a library which contains a function that takes two strings parameters:

void foo(const std::string& arg1, const std::string& arg2);

My library is going to be used by some people that don't like C++ and are only used to const char*.

To satisfy their likes, I changed the prototype:

void foo(const char* arg1, const char* arg2);

And made my first version a simple inline call:

inline void foo(const std::string& arg1, const std::string& arg2)
{
  foo(arg1.c_str(), arg2.c_str());
}

Of course, thanks to the std::string constructors, it would have worked almost the same way with just the first version. Writing this overload just avoids instanciating useless std::string in the case someone passes only const char*.

But now I wonder: is this overload really necessary or is it just premature optimization ?

Also, I'm feeling like this is somehow incomplete: should I write also void foo(const char* arg1, const std::string& arg2) and void foo(const std::string& arg1, const char* arg2) overloads ? What if I have 3, 4 or more (n) parameters ? Should I write 2n overloads ?

In short, have you ever faced a similar situation ? What choices did you made and why ?

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

别想她 2024-12-04 07:38:11

在我看来,有两个重载来处理组织内共存的两种不同的编程风格是合理的。

从技术上讲,这不仅仅是一种优化:

  1. const char* 可以是extern "C",因此对于来自其他语言的绑定可能有用,或者甚至来自跨越 dll 边界且标准库实现不兼容的其他 C++ 代码。
  2. 转换为 std::string 可能会抛出 bad_alloc,因此如果它不能以其他方式失败,那么 const char* 版本会很有用(如果您有C 样式字符串并希望在 nothrot 上下文中使用它。

另请注意,原则上 c_str() 可能会抛出 bad_alloc,但我怀疑任何实现实际上都会抛出异常。

2n 重载对我来说似乎不值得 - 如果有人混合 stringchar* 那么这不仅仅是编程风格的差异,他们由于某种原因实际上正在使用混合格式。由于他们已经在使用两者,因此他们可以自行转换。

这一切都假设该函数足够简单,您很乐意使用 const char* 参数来实现实际工作。如果基于 string 的实现要简单得多(例如,如果需要大量代码才能使其异常安全),那么无论如何,这可能会提高效率,因此不要提供任何重载,让它们的 const char* 转换为 string

IMO it's reasonable to have two overloads to handle two different programming styles that co-exist within your organization.

Technically it's not just an optimization:

  1. the const char* can be extern "C", so might be useful for bindings from other languages, or even from other C++ code across a dll boundary with incompatible standard library implementation.
  2. the conversion to std::string can throw bad_alloc, so if it cannot otherwise fail then the const char* version is useful if you have a C-style string and want to use it in a nothrow context.

Also beware that in principle c_str() can throw bad_alloc, but I doubt that any implementations actually do.

2n overloads doesn't seem worthwhile to me - if someone is mixing string and char* then it's not just a programming style difference, they're actually using mixed formats for some reason. Since they're using both already, they can convert for themselves.

This all assumes that the function is simple enough that you're happy to implement the actual work with const char* parameters. If the implementation based on string would be significantly simpler (for example if it takes significant code to make it exception-safe otherwise), then that probably wins over efficiency anyway, so don't provide any overloads, let their const char* convert to string.

蝶…霜飞 2024-12-04 07:38:11

只要您想使用 C++(而不是 C),第二个似乎就没有必要了,如果您有这样的情况:

void foo(const std::string& arg1, const std::string& arg2);

您可以使用 std::string的所有组合来调用它>char* 为:

char *ca, *cb;
std::string sa, sb;
//...
foo(ca,cb); //char*, char*
foo(sa,cb); //std:string, char*
foo(sa,sb); //std::string, std::string
foo(ca,sb); //char*, std::string

As long as you want to work with C++ (and not in C), the second one seems unneccessary, if you've this:

void foo(const std::string& arg1, const std::string& arg2);

You can call this with all combinations of std::string and char* as:

char *ca, *cb;
std::string sa, sb;
//...
foo(ca,cb); //char*, char*
foo(sa,cb); //std:string, char*
foo(sa,sb); //std::string, std::string
foo(ca,sb); //char*, std::string
很快妥协 2024-12-04 07:38:11

如果 const char * text 永远不为 null,则可以使用 string,因为它有隐式构造函数,因此 string 类版本就足够了。另一方面:如果 const char * text 可能为 null,则会生成运行时错误。

还有一件事:在 DLL 接口上,STL 并不是一个很好的选择。因此,如果该函数是 DLL 接口的一部分,则可以使用 C 样式字符串。

我可以这样做:

#include <string>
using namespace std;

void foo( const string arg0, const string arg1 )
extern "C" _declspec( dllexport ) void foo( const char * arg0, const char * arg1 )
{
  string string_arg0, string_arg1;
  if ( arg0 != 0 )
    string_arg0 = arg0;
  if ( arg1 != 0 )
    string_arg1 = arg1;
  foo(string_arg0, string_arg1);
}

If const char * text is never null, you could use string, because it has implictit constructor, so string class version could be enough. In other hand: if const char * text could be null, it generates runtime error.

One more thing: on DLL interface STL is not really good option. So if the function is part of a DLL interface, you may use C style strings.

I may do it in that way:

#include <string>
using namespace std;

void foo( const string arg0, const string arg1 )
extern "C" _declspec( dllexport ) void foo( const char * arg0, const char * arg1 )
{
  string string_arg0, string_arg1;
  if ( arg0 != 0 )
    string_arg0 = arg0;
  if ( arg1 != 0 )
    string_arg1 = arg1;
  foo(string_arg0, string_arg1);
}
紫竹語嫣☆ 2024-12-04 07:38:11

在这种情况下,您可能只需使用 (const char*,const char*) 并要求每个使用 std::string 的人都使用 c_str()。这样就不会有任何内存分配开销,只有人们必须编写额外的 c_str() 。

In that case, you could probably just have the (const char*,const char*) and ask everyone using std::string to use c_str(). That way there won't be any memory allocation overhead, only the extra c_str() that people will have to code up.

や莫失莫忘 2024-12-04 07:38:11

我的库将被一些不喜欢 C++ 的人使用,
仅用于 const char*。

告诉他们要勇敢地学习他们的编译器编译的语言。您采用 std::string,因为这就是 C++ 中的做法,如果他们不喜欢它,那么他们可以获得 C 编译器。

My library is going to be used by some people that don't like C++ and
are only used to const char*.

Tell them to man up and learn the language that their compiler compiles. You take std::string, because that's how to do it in C++, and if they don't like it, then they can get a C compiler.

抚笙 2024-12-04 07:38:11

我认为你目前的做法是正确的。在其中重载 const char* 并提供一个也提供 std::string 服务的包装器。

如果你的同事要使用 C 风格的字符指针,那么最好这样做(现在的方式)。参见以下案例;

char *p = 0;
foo(p);

void foo (const string &s)
{  // runtime error
}

演示。正如您所看到的,字符指针可能并不总是与 std::string 配合良好;那么为什么要冒险呢。即使人们可能不会进行这样的编码;但为了长期可维护性,您仍应避免此类潜在危险。

在函数内部,您始终可以选择使用 const char* 中的 std::string 并编写您的算法。

I think your present approach is correct. Where you overload for const char* and provide a wrapper which also serves std::string.

If your colleagues are going to use C-style character pointer than it's better to do that way (present way). See following case;

char *p = 0;
foo(p);

void foo (const string &s)
{  // runtime error
}

Demo. As you can see that character pointers may not go well always with std::string; so why to take chance. Even though people may not do such coding; still you should avoid such potential hazards for long time maintainability.

Inside the function you can always choose to have std::string from const char* and write your algorithm.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文