小编Mae*_*tro的帖子

C++ 入门第 5 版。函数模板重载

C++ Primer一书中,有一个关于函数模板重载的例子:

// 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 …
Run Code Online (Sandbox Code Playgroud)

c++ template-argument-deduction function-templates-overloading

6
推荐指数
1
解决办法
76
查看次数

是否在表达式中通过其名称和明确定义的引用多次修改对象?

您好,我有一个简单的问题:是否在同一个表达式中多次修改对象;一次通过其标识符(名称),第二次通过对它的引用或指向它的指针 未定义行为?

int i = 1;
std::cout << i << ", " << ++i << std::endl; //1- Error. Undefined Behavior

int& refI = i;
std::cout << i << ", " << ++refI << std::endl; //2-  Is this OK?

int* ptrI = &refI; // ptrI point to the referred-to object (&i)

std::cout << i << ", " << ++*ptrI << std::endl; // 3 is this also OK?
Run Code Online (Sandbox Code Playgroud)
  • 在第二个中,它似乎工作正常,但我对此感到困惑,因为从我所学到的;引用只是一个已经存在的对象的别名。并且对它的任何更改都会影响被引用的对象。因此,我在这里看到的是irefI是相同的,因此在同i一个表达式中不止一次修改同一个对象 ( )。

  • 但是为什么所有编译器都将语句 2 视为定义良好的行为?

  • 语句 3 …

c++ reference undefined-behavior c++17

5
推荐指数
1
解决办法
112
查看次数

std::strlen 如何在内部工作?

我一直在努力理解std::strlen()但徒劳无功:

AFAIKstrlen()以字节为单位返回以空字符结尾的常量字符串中的字符数。如果它不是以 null 结尾的,则行为是未定义的。除此之外,还可以。

所以:std::strlen("");是 0。

但是,因为我已经在 www.cppreference.com 上阅读过它,所以我发现了一个可能的实现:

// This is from:   https://en.cppreference.com/w/cpp/string/byte/strlen

std::size_t strlen(const char* start) {
     const char* end = start;
     while(*++end != 0);// I think this causes UB
     return end - start;
  }
Run Code Online (Sandbox Code Playgroud)

但是如果我运行它:

int main()
{
    const char cp1[] = "";
    const char cp2[] = "\0";
    const char cp3[] = "\0Hello";
    const char cp4[] = "H\0ello";
    const char cp5[1] = {};// UB?
    const char cp6[] = {'\0'};
    const char …
Run Code Online (Sandbox Code Playgroud)

c++ strlen

4
推荐指数
1
解决办法
234
查看次数

为什么 std::cin 不能隐式转换为 bool?

C++ Primer 第 5 版中。, 第 14 章讨论转换运算符:

在该标准的早期版本中,想要定义到 bool 的转换的类面临一个问题:因为 bool 是一种算术类型,转换为 bool 的类类型对象可以在任何需要算术类型的上下文中使用。

这种转换可能以令人惊讶的方式发生。特别是,如果 istream 转换为 bool,则以下代码将编译:

int i = 42;
cin << i; // this code would be legal if the conversion to bool were not explicit!
Run Code Online (Sandbox Code Playgroud)

该程序尝试在输入流上使用输出运算符。没有<<定义 for istream,所以代码几乎肯定是错误的。然而,这个代码可以使用布尔转换操作符转换cinbool。然后将生成的 bool 值提升为 int 并用作左移运算符的内置版本的左侧操作数。提升的布尔值(1 或 0)将左移 42 个位置。

输入流可以转换为表示流内部状态(成功或失败)的布尔值。我们曾经这样做:

while(std::cin >> str)...
Run Code Online (Sandbox Code Playgroud)

那么为什么不应该编译呢?

int x = 0;
std::cin << x;
Run Code Online (Sandbox Code Playgroud)

如果我使用显式转换,它会起作用:

(bool)cin << 5; // works although bad
Run Code Online (Sandbox Code Playgroud)

c++ conversion-operator

4
推荐指数
1
解决办法
147
查看次数

隐式移动与复制操作和遏制

当类中有一个未定义移动操作的成员时,我很难理解隐式移动操作:

int main() {
    struct A // no move: move = copy
    {
        A() = default;
        A(const A&) {
            cout << "A'copy-ctor\n";
        };
        A& operator=(const A&) {
            cout << "A'copy-assign\n";
            return *this;
        }
    };

    struct B
    {
        B() = default;
        A a; // does this make B non-moveable?
        unique_ptr<int> upi;
        // B(B&&) noexcept = default;
        // B& operator=(B&&)noexcept = default;
    };

    A a;
    A a2 = std::move(a); // ok use copy ctor instead of move one
    a2 = std::move(a); // …
Run Code Online (Sandbox Code Playgroud)

c++ copy-constructor move-constructor implicit-methods c++11

3
推荐指数
1
解决办法
353
查看次数

为什么 cmath 没有 pow 和 sqrt 模板?

好奇的是,为什么std::sqrtandstd::pow只针对单一类型的参数进行重载?为什么它们不作为函数/函子模板实现?

c++ cmath sqrt pow

3
推荐指数
1
解决办法
441
查看次数

如何在返回嵌入类型的泛型类之外实现成员函数?

我试图模拟class vector它,iterator所以这是问题所在:

template<class T>
class vec {
    public:
        vec();
    vec(const int);
    virtual ~vec();

    T* getElem()const;
    const int size()const;

    void resize(const int);
    void print()const;

    T& operator[](int);


    struct iterator {
        T* elem;
        iterator* operator++();
    };

    iterator begin();
    iterator end();

private:
    T* elem;
    int sz;
};
Run Code Online (Sandbox Code Playgroud)

现在我需要iterator begin();在课外实现vec:

template<class T>
 vec<T>::iterator vec<T>::begin() {

    vec<T>::iterator tmp;
    tmp.elem = elem;

    return tmp;
}
Run Code Online (Sandbox Code Playgroud)

我收到警告:

Severity    Code    Description Project File Line 
Warning C4346   iterator': dependent name is not …
Run Code Online (Sandbox Code Playgroud)

c++ templates

2
推荐指数
1
解决办法
46
查看次数

我可以使用分配器对象来释放另一个分配器分配的内存吗?

据我所知,std::allocator是由库引入的,用于分配未初始化的未构造内存块。所以:

std::allocator<int> a;
auto ptr = a.allocate(100);
auto e = ptr;
while (e != ptr + 5)
    a.construct(e++, 0);

for (auto tmp = ptr; tmp != e; )
    std::cout << *tmp++ << ", ";
std::cout << std::endl;

std::allocator<int> a2;
std::allocator<int> a3 = a;

for (auto tmp = ptr; tmp != e; )
    a.destroy(tmp++);

//for (auto tmp = ptr; tmp != e; )
//  a2.destroy(tmp++); // is it UB using a2 here to destroy elements?

//for (auto tmp = …
Run Code Online (Sandbox Code Playgroud)

c++ allocator

2
推荐指数
2
解决办法
130
查看次数

为什么我不能将数组传递给函数模板?

我有这个来自 C++ 第五版的例子:

template <typename T> T fobj(T, T); // arguments are copied
template <typename T> T fref(const T&, const T&); // references
string s1("a value");
const string s2("another value");
fobj(s1, s2); // calls fobj(string, string); const is ignored
fref(s1, s2); // calls fref(const string&, const string&)
              // uses premissible conversion to const on s1
int a[10], b[42];
fobj(a, b); // calls f(int*, int*)
fref(a, b); // error: array types don't match
Run Code Online (Sandbox Code Playgroud)

“在接下来的一对调用中,我们传递数组参数,其中数组的大小不同,因此具有不同的类型。在调用中fobj,数组类型不同的事实并不重要。两个数组都被转换为指针。模板参数类型中fobjint*。所述的呼叫fref …

c++ arrays pointers template-argument-deduction

2
推荐指数
1
解决办法
89
查看次数

为什么使用模板的参数的类型成员作为函数的返回类型可以在没有 typname 关键字的情况下工作,但在其他地方却不起作用?

正如我们所知,我们必须typename在使用模板类型参数的类型成员之前进行perpend ,因为没有它,编译器不知道我们是访问类型成员还是使用静态数据成员,因为类模板的定义不是尚未存在(实例化)

   template <typename T>
   void foo()
   {
       T::type x{}; // error: need a typename
       typename T::type y{}; // ok
   }
Run Code Online (Sandbox Code Playgroud)

到这里为止还可以,但是我发现了这个问题:

template <typename C_>
C_::value_type get_sum(C_ const& c) // no need to typename?!
{
    C_::value_type sum0{}; // errorL: need to typename keyword
    typename C_::value_type sum{};
    for(auto const& i : c)
        sum += i;
    return sum;
}
Run Code Online (Sandbox Code Playgroud)

正如您在函数模板主体中所看到的,编译器抱怨缺少关键字,typename但将其用作返回类型却没有抱怨?有人可以解释为什么吗?

c++ templates typename type-members

2
推荐指数
1
解决办法
54
查看次数