AFAIK,尽管我们无法创建大小为0的静态内存数组,但是我们可以使用动态数组来做到这一点:
int a[0]{}; // Compile-time error
int* p = new int[0]; // Is well-defined
Run Code Online (Sandbox Code Playgroud)
如我所读,p行为就像一个过去的元素。我可以打印p指向的地址。
if(p)
cout << p << endl;
Run Code Online (Sandbox Code Playgroud)
尽管我确定我们不能像使用迭代器(过去元素)那样取消引用该指针(过去元素),但是我不确定是否要增加该指针p?是否像迭代器一样具有未定义的行为(UB)?
p++; // UB?
Run Code Online (Sandbox Code Playgroud)据我所知std::allocator<T>::construct,在旧版本的C ++上仅需要两个参数;第一个是指向未构建的原始内存的指针,我们要在其中构造一个类型的对象,T第二个是用于初始化该对象的元素类型的值。因此,调用了复制构造函数:
struct Foo {
Foo(int, int) { cout << "Foo(int, int)" << endl; }
/*explicit*/ Foo(int) { cout << "Foo(int)" << endl; }
Foo(const Foo&) { cout << "Foo(const Foo&)" << endl; }
};
int main(int argc, char* argv[]) {
allocator<Foo> a;
Foo* const p = a.allocate(200, NULL); // second parameter is required on C++98 but on C++11 it is optional
// Foo* const p = a.allocate(200); // works fine on C++11 but not on …Run Code Online (Sandbox Code Playgroud) 我知道指针(指向数组元素)和迭代器可以递增/递减以遍历元素序列,并且可以在序列中来回跳转元素。
但是如果我增加一个指向单个对象的指针或向它添加一个整数值会发生什么?这是未定义的行为还是可以但我们无法访问该内存?
int x = 551;
int* p = &x;
++p;
--p;
std::cout << *p << '\n';
Run Code Online (Sandbox Code Playgroud)
因为我已经读过我们不应该增加/减少不指向序列或数组中元素的指针。
那么有人可以解释会发生什么以及我的示例是否正常(取消引用指针 p)?谢谢!
我们只能取消引用有效的指针,并且只能检查悬空内置指针指向的地址。我们无法访问它的值(它指向的对象地址中的值)。
int* ptr = nullptr;
if(ptr) // != 0x00000000
std::cout << *ptr << '\n';
ptr = new int(1000);
if(ptr) // != 0x00000000
std::cout << *ptr << '\n';
delete ptr; // still pointing at the address of that dynamic object but that object has been destroyed.
if(ptr) // succeeds or undefined behavior?
std::cout << *ptr << '\n'; // of course UB here
Run Code Online (Sandbox Code Playgroud)
所以我很清楚,但我关心的只是检查指针值是否安全或产生 UB?if(ptr)。因为我们假设我没有像 那样访问该地址中的值std::cout << *ptr。
我有一个关于STL容器的示例,所以我正在阅读它们,对我而言,重复使用range-for循环来打印容器的内容非常乏味。所以我想关于重载插入运算符<<因此我可以这样写:std::cout << container << std::endl;。
template<class T>
std::ostream& operator<<(std::ostream& out, const std::list<T>& v) {
for (const auto& e : v)
out << e << ", ";
return out;
}
int main() {
std::list<int> vi{ 10, 24, 81, 57, 2019 };
vi.pop_back();
std::cout << vi << std::endl; // 10, 24, 81, 57,
std::deque<std::string> names{ "Hello", "STL Containers" };
std::cout << names << std::endl; // error here. Bacause I've not overloaded << to take a std::deque<T> …Run Code Online (Sandbox Code Playgroud) 我正在使用向量,A其类类型为其元素类型。我<为我的类定义了关系运算符,但是当我比较其中两个向量时,它就会崩溃。
class A {
public:
explicit A(int){}
bool operator<(const A&)const {
return true; // for simplicity
}
};
int main() {
std::vector<A> v{ A(1), A(2), A(3), A(4), A(5) };
std::vector<A> v2{ A(0), A(2), A(4), A(6) };
std::cout << (v < v2) << std::endl; // program crashes here!
}
Run Code Online (Sandbox Code Playgroud)
我试图理解这一点,因为我已经读过STL容器使用元素类型的关系运算符?!
该程序在GCC上运行正常,但在MSVC ++ 14上崩溃,因此我收到断言对话框,抱怨该行 std::cout << (v < v2) << std::endl; // program crashes here!
@ user4581301指出的最有趣的事情是,如果我正确定义关系运算符,它将解决此问题:
class A {
public:
explicit A(int) {}
bool operator<(const A& a)const …Run Code Online (Sandbox Code Playgroud)我有一个简单的问题:在Lippman第10章的C ++入门5中。它说:“迭代器类别”:
迭代器类别
输入迭代器:可以读取序列中的元素。输入迭代器必须提供
相等和不相等运算符(
==,!=)比较两个迭代器前缀和后缀增量(
++)推进迭代器解引用运算符(
*)以读取元素;取消引用可能仅出现在作业的右侧箭头运算符(
->)是—的同义词,(*it).member即取消引用迭代器并从基础对象中获取成员。
他的意思是“去引用运算符(*)以读取元素;去引用只能出现在作业的右侧”:在“作业的左侧”。
我对此感到困惑。谢谢。
事实上,atemplate在使用之前不会被实例化,例如,如果我有这个类模板:
template <typename T>
struct Pow{
T operator()(T const& x) const{ return x * x; }
};
void func(Pow<double>); // Pow<double> instantiated here?
void func(Pow<int>){} // Pow<int> instantiated here?
int main(){
Pow<int> pi; // instantiated here?
func(pi); // Pow<int> instantiated here
}
Run Code Online (Sandbox Code Playgroud)
那么模板具体什么时候被实例化呢?
那么是在声明的Pow<int>时候实例化的吗func(Pow<int>)?
如果我没有使用Pow<int>inmain()那么它是否因为使用 infunc作为其参数的类型而被实例化?
你好,我有一个来自 C++ 入门的例子:
Run Code Online (Sandbox Code Playgroud)template <typename T> void f(T&& x) // binds to nonconstant rvalues { std::cout << "f(T&&)\n"; } template <typename T> void f(T const& x) // lvalues and constant revalues { std::cout << "f(T const&)\n"; }
这是我测试输出的尝试:
int main(){
int i = 5;
int const ci = 10;
f(i); // f(T& &&) -> f(int&)
f(ci); // f(T const&) -> f(int const&)
f(5); // f(T &&) -> f(int&&)
f(std::move(ci)); // f(T&&) -> f(int const&&)
cout << '\n';
}
Run Code Online (Sandbox Code Playgroud)
输出:
f(T&&) …Run Code Online (Sandbox Code Playgroud) 正如我们所知,派生类public和protected成员的直接或间接基类在派生类中可用。
所以我有这个例子:
struct Foo{int x_ = 10;};
struct Bar : Foo{};
struct FooBar : Bar{
void f()const{
std::cout << &x_ << " : " << x_ << '\n';
std::cout << &Foo::x_ << " : " << Foo::x_ << '\n';
std::cout << &Bar::x_ << " : " << Bar::x_ << '\n';
std::cout << &FooBar::x_ << " : " << FooBar::x_ << '\n';
}
};
int main(){
FooBar fb{};
fb.f();
}
Run Code Online (Sandbox Code Playgroud)
当我编译并运行程序时,我得到输出:
0x7ffc2f7ca878 : 10
1 : 10 …Run Code Online (Sandbox Code Playgroud)