为什么我的std :: string被转换为std :: basic_string <char>?

Moe*_*oeb 2 c++ stack

错误

stack.cc:53:28: error: no matching function for call to ‘Stack<std::basic_string<char> >::push(std::string)’
stack.cc:53:28: note: candidate is:
stack.cc:32:11: note: Stack<T>& Stack<T>::push(T&) [with T = std::basic_string<char>]
Run Code Online (Sandbox Code Playgroud)

stack.cc

#include<iostream>

template <typename T>
class Stack {
private:
    T* array_;
    int length_;
    T* last_;
    void expandArray();

public:
    Stack(int length = 8) {
        array_   = new T[length];
        length_  = length;
        last_    = array_;
    }

    Stack<T>& push(T&);
    T pop();
};

template<typename T>
void Stack<T>::expandArray() {
    T* array_temp = new T[length_ << 1];
    memcpy(array_temp, array_, length_);
    std::swap(array_, array_temp);
    delete[] array_temp;
    length_ <<= 1;
}

template<typename T>
Stack<T>& Stack<T>::push(T& data) {
    if (last_ == (array_ + length_ - 1)) {
        expandArray();
    }
    last_[0] = data;
    last_++;
    return *this;
}

template<typename T>
T Stack<T>::pop() {
    if(array_ != last_) {
        T temp = last_[0];
        last_--;
        return temp;
    }
    return NULL;
}

int main() {
    Stack<std::string> s;
    s.push(std::string("a"))
     .push(std::string("b"))
     .push(std::string("c"))
     .push(std::string("d"));
    std::cout << s.pop() << std::endl;
    std::cout << s.pop() << std::endl;
    std::cout << s.pop() << std::endl;
    std::cout << s.pop() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

想明白为什么一个转换的发生std::stringstd::basic_string<char>

请随时评论代码质量.

old*_*inb 7

实际问题是您尝试传递对参数中创建的对象的引用,而不是存储在变量中.看到那个T&论点Stack<T>::push?你不能在这里传递你的临时因为它是非const参考.尝试如下......

Stack<T>& push(const T&);
Run Code Online (Sandbox Code Playgroud)

也可以使用此签名进行实施.


话虽这么说,知道这std::string仅仅是一种类型std::basic_string<char>.这是因为字符串的功能也可以扩展到其他字符类型 - std::wstringfor wchar_t,std::u16stringfor char16_tstd::u32stringfor char32_t.;-)

请参见C++ 11规范的§21.4类模板basic_string[basic.string].

// basic_string typedef names
typedef basic_string<char> string;
typedef basic_string<char16_t> u16string;
typedef basic_string<char32_t> u32string;
typedef basic_string<wchar_t> wstring;
Run Code Online (Sandbox Code Playgroud)

请注意,您不应该依赖iostream包含string在您身上.您还应该包括cstring并指定memcpy呼叫范围.


顺便说一下,你应该真正考虑使用初始化列表Stack的构造函数...请参阅以下内容.

Stack(int length = 8) : length_(length), array_(new T[length]), last_(array_) { }
Run Code Online (Sandbox Code Playgroud)

请注意,这在array_前面last_作为类成员声明正常运行;-)


... 最后要注意.你pop是不正确的,因为您传回元素过去的顶部.相反,尝试以下内容......

template<typename T>
T Stack<T>::pop() {
    if (array_ != last_) {
        return *--last_;
    }
    /* other stuff here */
}
Run Code Online (Sandbox Code Playgroud)

您需要解除引用之前递减,因为last_点数超过顶部.作为附注,你也会返回一份std::string来自的副本pop,即使你声明你想避免这样做.

请注意,您不应该返回,NULL因为这不是指针类型.事实上,你只需要创建一个std::string带有const char *... 的构造函数,在这种情况下明确禁止NULL.见§21.4.28-9......

basic_string(const charT* s, const Allocator& a = Allocator());
Run Code Online (Sandbox Code Playgroud)

要求: s不应为空指针.