与Microsoft不同的新例外

时间:2010-03-12 21:13:48

标签: c++ visual-c++ g++ new-operator

由于我正在为Windows和Linux编写代码,因此我遇到了许多问题。 Microsoft Visual C ++没有stdint标头,但为此,我编写了自己的标题。

现在我发现MS C ++的新运算符没有抛出异常,所以我想尽快解决这个问题。我知道我可以在括号中定义带参数的宏,我可以定义一个替换

的宏
MyClass x = new MyClass();

#ifdef MSC_VER
if(!(MyClass x = new MyClass())
{
    throw new std::bad_alloc();
}
#else
MyClass x = new MyClass();
#endif

(或类似的东西),AND在MS C ++和G ++中工作?

或者,如果不可能,则运行代码的批处理文件执行此操作? 我已经变得非常依赖抛出这个异常。

3 个答案:

答案 0 :(得分:2)

微软的C ++编译器非常接近100%符合标准,除了一些不起眼的东西。不在新的中抛出异常不是其中之一。

除此之外,你不能编写一个可以检测到该表达式并相应地处理它的宏,除非你想重写new的所有用法(击败目的)。

答案 1 :(得分:1)

实际上,有一个简单的解决方案:replace operator new,其中一个会导致分配失败。 (链接代码是标准C ++,可能需要对编译器进行调整。您可以将malloc用于allocate_from_some_other_source并为deallocate_from_some_other_source使用。)


旧答案

(这些替换确实需要更改调用代码,因为C ++语法的结构是不可避免的。但是,它们被编写为需要最小的更改才能用作逻辑插入式替换。真正的解决方案是从过去7年左右升级到MSVC版本。听起来你正在使用的MSVC6实际上是在1998年C ++标准之前发布的。)

解决一般情况很难,但这是一个近似值:

struct Thrower { // needs a better name
  void* p;
  Thrower(void* p) : p(p) {
    if (!p) throw std::bad_alloc();
  }
  ~Thrower() {
    if (std::uncaught_exception()) operator delete(p);
    // this is true when the object's ctor throws
  }
  operator void*() const { return p; }
};

int main() {
  int* p = new (Thrower(operator new(sizeof(int))) int(42);
  // int is a placeholder type, but shows you can still pass ctor parameters

  // with a macro becomes:
#define MYNEW(T) new (Thrower(operator new(sizeof(T))) T
  int* p = MYNEW(int)(42);
}

对于已知参数,您可以避免使用宏并保持简单:

template<class T>
T* my_new() {
  T* p = new T();
  if (!p) throw std::bad_alloc();
  return p;
}
template<class T>
T* my_new(T const& value) {
  T* p = new T(value);
  if (!p) throw std::bad_alloc();
  return p;
}

int main() {
  int* p = my_new<int>();
  int* p2 = my_new<int>(*p);
}

答案 2 :(得分:1)

最简单的替代方法是编写自己的operator new实现,覆盖编译器的默认实现(如果您的MSVC版本支持它)。罗杰在他的链接答案中也提出了这一点。

以下程序说明了这种尝试。 operator new使用mallocfree从堆中分配内存。如果您正在为G ++和MSVC进行条件编译,您还可以使用HeapAllocHeapFree代替mallocfree来实现更加面向WinAPI的方法。

#include <iostream>
#include <cstdlib>

void *operator new(unsigned int size) throw (std::bad_alloc) {
    void *ptr = malloc(size);

    if (!ptr)
        throw std::bad_alloc();
    return ptr;
}

void operator delete(void *ptr) throw () {
    free(ptr);
}

// Sample code to test the implementation.
int main(int argc, char **argv) {
    int *values[10];

    for (int i = 0; i < 10; ++i)
        values[i] = new int(i);
    for (int i = 0; i < 10; ++i)
        std::cout << *values[i] << std::endl;
    for (int i = 0; i < 10; ++i)
        delete values[i];
    return 0;
}