Почему исходный код sgi stl использует двойную двоеточие перед новой функцией оператора?
Я читаю исходный код стандартной библиотеки шаблонов SGI. Я считаю, что функция operator new
всегда имеет перед собой двойную двоеточие. Вот так:
T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));
operator new
можно напрямую вызвать без добавления поля ::
, то почему stl-кодеры пишут таким образом? Какая ловушка или ситуация могут возникнуть, если мы не используем ::
перед ними.
Ответы
Ответ 1
Вы можете перегрузить оператор new для класса, а его префикс "::" вызовет глобальный "по умолчанию" оператор new вместо возможной перегрузки. Например:
#include <iostream>
class Foo
{
public:
Foo() { std::cout << "Foo::Foo()" << std::endl; }
void * operator new(size_t )
{
std::cout << "Foo::operator new()" << std::endl;
return static_cast<Foo *>(malloc(sizeof(Foo)));
}
};
int main()
{
Foo foo;
std::cout << "----------------------" << std::endl;
Foo * p = new Foo;
std::cout << "----------------------" << std::endl;
Foo * q = ::new Foo;
}
напечатает
Foo::Foo()
----------------------
Foo::operator new()
Foo::Foo()
----------------------
Foo::Foo()
Изменить: код, который был отключен, действительно не о новом операторе, который определен в области класса. Лучшим примером может быть следующее:
#include <iostream>
namespace quux {
void * operator new(size_t s)
{
std::cout << "quux::operator new" << std::endl;
return malloc(s);
}
void foo()
{
std::cout << "quux::foo()" << std::endl;
int * p = static_cast<int*>(operator new(sizeof(int)));
}
void bar()
{
std::cout << "quux::bar()" << std::endl;
int * p = static_cast<int*>(::operator new(sizeof(int)));
}
} // namespace quux
int main()
{
quux::foo();
quux::bar();
}
который печатает
quux::foo()
quux::operator new
quux::bar()
Ответ 2
::operator new
в С++ - это глобальный распределитель памяти, который вызывается каждый раз, когда требуется определенное количество байтов для одного объекта. Обратите внимание, что возвращаемое значение равно void *
и что ::operator new(size_t)
имеет дело с необработанными байтами, а не с объектами.
В основном это С++-аналог malloc
с просто смешным именем.
Вместо этого используется выделенный глобальный распределитель ::operator new[](size_t sz)
для выделения памяти для массивов объектов.
Эти два оператора, их аналоги ::operator delete
и ::operator delete[]
, а также nothrow
версия распределители используются для всех потребностей памяти во время выполнения С++.
Они могут быть реализованы с точки зрения вызовов malloc
/free
или нет. Что гарантирует, что malloc
и free
не использовать их (таким образом, вы можете вызвать malloc
и free
если вы хотите переопределять эти функции без риска бесконечной рекурсии).
Ответ 3
Двойная двоеточие используется для предотвращения вызова T:: operator new() (если определены).
Ответ 4
Чтобы вызвать operator new
из глобального пространства имен, если пользователь (или кто-то) решил использовать оператор new
.