如何防止从“0”构造 std::string 时出现问题?

发布于 2024-11-17 08:46:30 字数 578 浏览 4 评论 0原文

void foo (const std::string &s) {}

int main() {
  foo(0);   //compiles, but invariably causes runtime error
  return 0;
}

编译器 (g++ 4.4) 显然将 0 解释为 char* NULL,并通过调用 string::string(const char) 构造 s *, const 分配器 &a = 分配器())。这当然是无用的,因为 NULL 指针不是指向 C 字符串的有效指针。当我尝试调用 foo(1) 时,不会出现这种误解,这有助于产生编译时错误。

是否有可能在编译时出现这样的错误或警告

void bar(const std::string &s, int i=1);

当我不小心调用像bar(0) 这样的函数,忘记了 string 以及实际含义时, 有i=0

void foo (const std::string &s) {}

int main() {
  foo(0);   //compiles, but invariably causes runtime error
  return 0;
}

The compiler (g++ 4.4) apparently interprets 0 as char* NULL, and constructs s by calling string::string(const char*, const Allocator &a = Allocator()). Which is of course useless, because the NULL pointer is not a valid pointer to a c-string. This misinterpretation does not arise when I try to call foo(1), this helpfully produces a compile-time error.

Is there any possibility to get such an error or warning at compile-time when I accidentally call a function like

void bar(const std::string &s, int i=1);

with bar(0), forgetting about the string, and actually meaning to have i=0?

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

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

发布评论

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

评论(3

风苍溪 2024-11-24 08:46:30

这有点丑陋,但您可以创建一个模板,该模板在实例化时会产生错误:

template <typename T>
void bar(T const&)
{
    T::youHaveCalledBarWithSomethingThatIsntAStringYouIdiot();
}

void bar(std::string const& s, int i = 1)
{
    // Normal implementation
}

void bar(char const* s, int i = 1)
{
    bar(std::string(s), i);
}

然后使用它:

bar(0); // produces compile time error
bar("Hello, world!"); // fine

This is kind of ugly, but you could create a template that will produce an error when instantiated:

template <typename T>
void bar(T const&)
{
    T::youHaveCalledBarWithSomethingThatIsntAStringYouIdiot();
}

void bar(std::string const& s, int i = 1)
{
    // Normal implementation
}

void bar(char const* s, int i = 1)
{
    bar(std::string(s), i);
}

Then using it:

bar(0); // produces compile time error
bar("Hello, world!"); // fine
幻梦 2024-11-24 08:46:30

一种比较干净的解决方法......

#include <cassert>

void foo (const std::string &s)
{
    // Your function
}

void foo(const char *s)
{
     assert(s != 0);
     foo(std::string(s));
}

One somewhat clean workaround...

#include <cassert>

void foo (const std::string &s)
{
    // Your function
}

void foo(const char *s)
{
     assert(s != 0);
     foo(std::string(s));
}
蘸点软妹酱 2024-11-24 08:46:30

实际上静态断言也可以工作。
考虑一下:

void foo (const std::string &s)
{
    // Your function
}

void foo(const char *s)
{
    #ifdef CPP_OH_X
    static_assert(s == 0, "Cannot pass 0 as an argument to foo!");
    #else
    typedef int[(s != 0) ? 1 : -1] check;
    #endif
    foo(std::string(s));
}

这里的想法是使用 static_assert,这是 C++ 中即将推出的功能,并且已经在各种编译器中实现;主要是支持 C++0x 的。现在,如果您不使用 C++0x,则可以使用替代方法,该方法基本上类型定义失败时具有负值的整数。不允许的东西会在编译时产生错误

Actually static asserts would work too.
consider this:

void foo (const std::string &s)
{
    // Your function
}

void foo(const char *s)
{
    #ifdef CPP_OH_X
    static_assert(s == 0, "Cannot pass 0 as an argument to foo!");
    #else
    typedef int[(s != 0) ? 1 : -1] check;
    #endif
    foo(std::string(s));
}

The idea here is to use static_assert which is a upcoming feature in C++ and is already implemented in various compilers; primarly the ones that support C++0x. Now if you're not using C++0x you can use the alternitive method, which basicly typedefs an integer with a negitive value on failure. Something which is not allowed and will produce an error at compile time

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