我正在再次阅读“C++ Primer,第 5 版”。在关于模板的第16章中,有一个“模板非类型参数”的例子:
template<unsigned N, unsigned M>
int compare(const char (&p1)[N], const char (&p2)[M])
{
return strcmp(p1, p2);
}
int main()
{
cout << compare("hi", "mom") << endl;
cout << strcmp("hi", "mom") << endl;
std::cout << "\ndone!\n";
}
Run Code Online (Sandbox Code Playgroud)
众所周知,strcmp()
比较两个字符串并返回0
相等,如果str1
大于则为str2
正值,如果str1
小于则为负值str2
,这就是我在main()
调用strcmp()
.
问题出在调用strcmp()
模板函数内部的书中示例中,所以当我运行程序时,我得到:
输出:
-5
-1
Run Code Online (Sandbox Code Playgroud)
代码中有什么问题?为什么两者对相同的参数给出不同的值?
我有一个constexpr类Debug:
struct Debug {
constexpr Debug(bool a, bool b, bool c) : a(a), b(b), c(c) {}
bool a, b, c;
constexpr bool get() const { return a; }
};
int main() {
Debug dbg(true, false, false); // is dbg constexpr object?
constexpr Debug dbg2(0, 0, 0); // is constexpr redundant here?
}
Run Code Online (Sandbox Code Playgroud)
如您所见,这dbg
是一个constexpr对象,因为它是用constexpr构造函数初始化的,所以如果我用constexpr对其进行限定,那有什么意义呢?
dbg
和dbg2
。谢谢。我在这里有一个简单的示例:我使用类型别名using using
关键字作为引用类型,然后我想知道是否可以通过指针运算符(*)使用该类型别名来声明对指针的引用:
int main(){
using ref_int = int&;
int x = 10;
int* p = &x;
//int*(&rpx) = p;
//ref_int * rptrx = p; // pointer to reference is not allowed.
*ref_int(rptrx) = p; // rptrx is undefined
}
Run Code Online (Sandbox Code Playgroud)
因为出于好奇,当我使用Element的类型时,std::vector<int>::reference
我想将其与指针运算符结合*
以声明对指针的引用:
int* ptr = new int(1000);
std::vector<int>::*(reference rptr) = ptr; // error: expected expression
Run Code Online (Sandbox Code Playgroud)但是我可以结合使用指针类型别名和引用运算符“&”来声明它:
using pInt = int*;
int i = 57;
int* ptrI = &i;
pInt(&rpInt) = ptrI;
cout << *rpInt << endl;
Run Code Online (Sandbox Code Playgroud)**我知道我没有指向引用的指针,因为引用只是已有对象的别名,而指针是一个对象,因此我们可以有一个指向它的指针或引用。
你好,我有一个简单的问题:
class A
{
public:
A(int);
A(const A&);
A& operator=(const A&);
~A();
private:
int* ptr_;
friend bool operator<(const A&, const A&);
friend void swap(A&, A&);
};
A::A(int x) :
ptr_(new int(x))
{}
A::A(const A& rhs) :
ptr_(rhs.ptr_ ? new int(*rhs.ptr_) : nullptr)
{}
A& A::operator = (const A & rhs)
{
int* tmp = rhs.ptr_ ? new int(*rhs.ptr_) : nullptr;
delete ptr_;
ptr_ = tmp;
return *this;
}
A::~A()
{
delete ptr_;
}
bool operator<(const A& lhs, const A& rhs) …
Run Code Online (Sandbox Code Playgroud) 我正在阅读C ++ Primer,第5版。当谈论冲洗流时,它说:
输出流可能会绑定到另一个流。在这种情况下,每当读取或写入绑定流时,都会刷新绑定流的缓冲区。默认情况下,cin和cerr都与cout绑定在一起。因此,读取cin或写入cerr会冲洗cout中的缓冲区。
我试图通过一个例子来理解这一点:
int main() {
std::ofstream out("data.txt");
std::ifstream in("data.txt");
//in.tie(&out);// commenting this will print nothing
out << "Hello there!";
std::string str;
while (in >> str)
std::cout << str << " ";
out.close();
in.close();
}
Run Code Online (Sandbox Code Playgroud)
如您在上方看到的输入和输出文件流对象in
并out
使用相同的文件,因此输出一个打开文件“ data.txt”并向其中写入一些行,但不保存它,输入流尝试读取内容未保存文件的内容。
如果将输入流对象绑定到该对象in
,out
则可以正确获取内容。这是否意味着in
军队out
被刷新?
如果我注释掉该行,in.tie(&out)
那么我不会使用in来获取内容?
请在这里向我解释它是如何工作的。先感谢您。
据说在C ++入门5th版中,为所有参数提供默认参数的构造函数也定义了默认构造函数:
class Point {
public:
//Point(); // no need to define it here.
Point(int x = 0, int y = 0) : x_(x), y_(y){
std::cout << "Point(int=0, int=0)" << std::endl;
} // synthesize default constructor Point()
int x_;
int y_;
};
int main(){
Point pt; // default ctor Point() or Point(int, int)?
Point pt2 = Point(); // this won't compile?!
}
Run Code Online (Sandbox Code Playgroud)
正如你可以看到上面我想出于某种原因调用默认的构造函数Point()
不是Point(int, int)
,但我得到了后者不是默认的构造函数?
那么是否可以调用由为所有参数提供默认参数的构造函数提供的类的默认构造函数?谢谢。
这是 C++ 入门第 5 版的练习:
“练习 16.26:假设NoDefault
是一个没有默认构造函数的类,我们可以显式实例化vector<NoDefault>
吗?如果没有,为什么不呢?”
这是我的猜测:
是的,我们可以实例化它:
template <typename T>
class Foo
{
public:
void func(){cout << x_.value_ << endl;}
private:
T x_;
};
class Bar
{
public:
Bar(int x) : value_(x){}
void print(){}
private:
int value_{};
template <class T>
friend class Foo;
};
extern template class Foo<Bar>; // instantiation declaration
template class Foo<Bar>; // instantiation definition
int main()
{
// Foo<Bar> f;
}
Run Code Online (Sandbox Code Playgroud)
代码工作正常,但如果我取消注释 main 中的行,我会按预期出现错误,因为Bar
它不是默认构造的。
如果我使用相同的类Bar
作为元素类型,std::vector
它不起作用: …
我已经了解如何std::move
工作并实现我自己的版本仅供练习。现在我试图了解如何std::forward
工作:
到目前为止,我已经实现了这一点:
#include <iostream>
template <typename T>
T&& forward_(T&& x)
{
return static_cast<T&&>(x);
}
/*template <typename T>
T&& forward_(T& x)
{
return static_cast<T&&>(x);
}*/
void incr(int& i)
{
++i;
}
void incr2(int x)
{
++x;
}
void incr3(int&& x)
{
++x;
}
template <typename T, typename F>
void call(T&& a, F func)
{
func(forward_<T>(a));
}
int main()
{
int i = 10;
std::cout << i << '\n';
call(i, incr);
std::cout << i << '\n';
call(i, incr2); …
Run Code Online (Sandbox Code Playgroud) 在关于异常规范的 C++ Primer 上noexcept
,据说指向可能抛出隐式(没有异常规范定义,例如:)void(*p)();
或显式(void(*p)() noexcept(false);
)的函数的指针可以指向任何函数,甚至指向不抛出的函数。
另一方面,一个不能抛出异常的函数指针(noexcept
例如void(*p) noexcept;
)只能指向一个不会抛出异常的函数。
我发现这非常合乎逻辑,因为第一个指针可以从抛出函数指针指向非抛出函数,而第二个指针也很合乎逻辑。
我尝试过这个来了解更多:
void func1(){ // may throw
std::cout << "func1()\n";
}
void func2() noexcept(false){ // may throw
std::cout << "func2()\n";
}
void func3() noexcept(true){ // won't throw
std::cout << "func3()\n";
}
void func4() noexcept{ // won't throw
std::cout << "func4()\n";
}
int main(int argc, char* argv[]){
void(*pFn1)();
pFn1 = func1; // OK
pFn1 = func2; // OK
pFn1 = func3; // OK
pFn1 …
Run Code Online (Sandbox Code Playgroud) 在C++ Primer一书中,有一个关于函数模板重载的例子:
Run Code Online (Sandbox Code Playgroud)// print any type we don't otherwise handle template <typename T> string debug_rep(const T &t) { cout << "debug_rep(T const&)\n"; ostringstream ret; // see § 8.3 (p. 321) ret << t; // uses T's output operator to print a representation of t return ret.str(); // return a copy of the string to which ret is bound } // print pointers as their pointer value, followed by the object to which the pointer points // NB: this …
c++ template-argument-deduction function-templates-overloading